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
analy
This should do the trick for every item
(tested on SQLite):
SELECT
day
,price
,price - (SELECT t2.price
FROM mytable t2
WHERE
t2.item = t1.item AND
t2.day < t1.day
ORDER BY t2.day DESC
LIMIT 1
) AS change
FROM mytable t1
This assumes the combination between day
and item
is unique. And the way it works is by taking all the values less than the given day
, sorting descending and then LIMIT
just the first value, simulating a LAG
function.
For a LEAD
behavior, just flip <
to >
and DESC
to ASC
.
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;
Assuming that you don't delete this will work:
SELECT t2.DAY, t2.price, t2.price-t1.price
FROM TABLENAME t1, TABLENAME t2
WHERE t1.rowid=t2.rowid-1
This works because every row has its own rowid even if you dont specify it in the CREATE
statement.
If you do delete, it becomes:
SELECT t2.day, t2.price, t2.price-t1.price
FROM
(SELECT l1.day, l1.price,
(SELECT COUNT(*)
FROM TABLENAME l2
WHERE l2.rowid < l1.rowid) AS count
FROM TABLENAME l1) AS t1,
(SELECT l1.day, l1.price,
(SELECT COUNT(*)
FROM TABLENAME l2
WHERE l2.rowid < l1.rowid) AS count
FROM TABLENAME l1) AS t2
WHERE t1.count=t2.count-1
This works under the assumption that rowids are always increasing.
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.