Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a SQLite view where a row depends on the previous row

Tags:

sql

sqlite

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'
like image 689
eaolson Avatar asked Apr 04 '12 00:04

eaolson


People also ask

How do you access the previous row and next row value in a SELECT statement?

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.

How do I SELECT a previous row value in SQL?

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.

How do I SELECT a specific row in SQLite?

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.

Can you create views in SQLite?

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];


2 Answers

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

like image 169
Lukasz Szozda Avatar answered Sep 20 '22 17:09

Lukasz Szozda


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.

like image 20
chacham15 Avatar answered Sep 19 '22 17:09

chacham15