I'd like to create a view in SQLite where a field in one row depends on the value of a field in the previous row. I could do this in Oracle using the LAG
analytic function, but not sure how to go about it in SQLite.
For example, if my table looked like:
ITEM DAY PRICE
apple 2011-01-07 1.25
orange 2011-01-02 1.00
apple 2011-01-01 1.00
orange 2011-01-03 2.00
apple 2011-01-08 1.00
apple 2011-01-10 1.50
I'd like my view to look like, with WHERE item = 'apple'
:
DAY PRICE CHANGE
2011-01-01 1.00 (null)
2011-01-07 1.25 0.25
2011-01-08 2.00 0.75
2011-01-10 1.50 -0.50
Edit:
The equivalent of the query I'm looking for would look in Oracle something like (haven't tried this, but I think this is correct):
SELECT day, price,
price - LAG( price, 1 ) OVER ( ORDER BY day ) AS change
FROM mytable
WHERE item = 'apple'
In other words, by using the LAG() function, from the current row, you can access data of the previous row, or the row before the previous row, and so on. The LAG() function can be very useful for comparing the value of the current row with the value of the previous row.
1) You can use MAX or MIN along with OVER clause and add extra condition to it. The extra condition is "ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING" which will fetch previous row value. Check this: SELECT *,MIN(JoiningDate) OVER (ORDER BY JoiningDate ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS EndDate.
Typically to get a specific row you can always request them by rowid , e.g. SELECT name FROM UnknownTable WHERE rowid = 1; However, there are some atypical situations that preclude this. You'll really want to read up on rowids to ensure that your table is going to behave as you want.
SQLite views can be created from a single table, multiple tables, or another view. Following is the basic CREATE VIEW syntax. CREATE [TEMP | TEMPORARY] VIEW view_name AS SELECT column1, column2..... FROM table_name WHERE [condition];
Oracle equivalent is correct. Starting from SQLite 3.25.0 you could use LAG
natively:
WITH mytable(ITEM,DAY,PRICE) AS (
VALUES
('apple', CAST('20110107' AS DATE), 1.25),
('orange', CAST('20110102' AS DATE), 1.00),
('apple', CAST('20110101' AS DATE), 1.00),
('orange', CAST('20110103' AS DATE), 2.00),
('apple', CAST('20110108' AS DATE), 2.00),
('apple', CAST('20110110' AS DATE), 1.50)
)
SELECT day, price, price-LAG(price) OVER (ORDER BY day) AS change
FROM mytable
WHERE item = 'apple'
ORDER BY DAY;
db<>fiddle demo
Its the same idea as the other, but just uses the fields instead of the rowid. This does exactly what you want:
CREATE TABLE Prices (
day DATE,
price FLOAT
);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '+1 day'), 0.5);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '+0 day'), 1);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '-1 day'), 2);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '-2 day'), 7);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '-3 day'), 8);
INSERT INTO Prices(day, price) VALUES(date('now', 'localtime', '-4 day'), 10);
SELECT p1.day, p1.price, p1.price-p2.price
FROM
Prices p1, Prices p2,
(SELECT t2.day AS day1, MAX(t1.day) AS day2
FROM Prices t1, Prices t2
WHERE t1.day < t2.day
GROUP BY t2.day) AS prev
WHERE p1.day=prev.day1
AND p2.day=prev.day2
If you want to add the WHERE item='apple'
bit you'd add that to both WHERE
clauses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With