2012-04-04 3 views
7

SQLiteで1つの行のフィールドが前の行のフィールドの値に依存するビューを作成したいとします。私はLAG解析関数を使ってOracleでこれを行うことができましたが、SQLiteでどうやってそれを行うかはわかりません。私はWHERE item = 'apple'と、見えるように私の見解を希望行が前の行に依存するSQLiteビューを作成する

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 

は例えば、私のテーブルには、ように見えた場合

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 

編集:

の同等私が探しているのは、Oracleのようなものです(これは試していませんが、これは正しいと思いますが)。

SELECT day, price, 
     price - LAG(price, 1) OVER (ORDER BY day) AS change 
    FROM mytable 
WHERE item = 'apple' 
+0

"前へ"を定義します。現在のレコードの1日前の日付の単一の許可されたレコードのように見えます。それはいつも真実ですか? –

+0

いいえ、私はこの例を拡張しました。 「前の」とは、基本的には、問題が発生した行の前に行があることを意味します。 – eaolson

+0

「順序付け」を定義します。基本的に、問題は、SQLデータベース(定義による)は、特に列名、検索時に指定するもの以外の行の順序付けの概念を持たないことです。一般的には望みの結果を得ることができますが、ビュー定義の関係代数を使って「前の行」を導き出す必要があります。そのためには、「前の」定義方法を明示する必要があります言語。 –

答えて

0

あなたはこれが動作します削除しないと仮定すると:


SELECT t2.DAY, t2.price, t2.price-t1.price 
FROM TABLENAME t1, TABLENAME t2 
WHERE t1.rowid=t2.rowid-1 

すべての行は、あなたがCREATE文でそれを指定するいけない場合でも、独自のROWIDを持っているので、これは動作します。

削除を行う場合は、次のようになります。


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 

これは、行IDは常に増加しているという仮定の下で動作します。

+0

これは、テーブルの履歴(行が挿入された順序、更新されないことなど)を前提にしています。 – eaolson

2

他のものと同じアイデアですが、単にROWIDの代わりにフィールドを使用します。これは正確に何をしたいん:


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 

あなたがWHERE item='apple'ビットを追加したい場合は、両方のWHERE句にそれを追加したいです。

1

これは(SQLiteの上でテスト)すべてのitemのためのトリックを行う必要があります。

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 

これはdayitem間の組み合わせがユニークであると想定します。そして、それが動作する仕方はより小さい与えられたdayを取り、降順を降順にして、次にLIMITLAGの機能をシミュレートするだけの値にすることです。

LEADの動作では、<から>DESCからASCにフリップされます。