40
| time                | company | quote |
+---------------------+---------+-------+
| 0000-00-00 00:00:00 | GOOGLE  |    40 |
| 2012-07-02 21:28:05 | GOOGLE  |    60 |
| 2012-07-02 21:28:51 | SAP     |    60 |
| 2012-07-02 21:29:05 | SAP     |    20 |

MySQL のこのテーブルでラグを実行して、引用符で差を出力するにはどうすればよいですか。たとえば、次のようになります。

GOOGLE | 20
SAP    | 40  
4

3 に答える 3

59

これは私のお気に入りの MySQL ハックです。

これは、ラグ関数をエミュレートする方法です。

SET @quot=-1;
select time,company,@quot lag_quote, @quot:=quote curr_quote
  from stocks order by company,time;
  • lag_quote前の行の見積もりの​​値を保持します。最初の行の @quot は -1 です。
  • curr_quote現在の行の引用符の値を保持します。

ノート:

  1. order by句は、通常のウィンドウ関数と同様に重要です。
  2. company同じ の引用符の差を計算していることを確認するために、ラグを使用することもできますcompany
  3. 同じ方法で行カウンターを実装することもできます@cnt:=@cnt+1

このスキームの優れた点は、集計関数の使用、ストアド プロシージャ、アプリケーション サーバーでのデータ処理などの他のアプローチと比較して、計算量が非常に少ないことです。

編集:

あなたが言及した形式で結果を取得するという質問に来ます:

SET @quot=0,@latest=0,company='';
select B.* from (
select A.time,A.change,IF(@comp<>A.company,1,0) as LATEST,@comp:=A.company as company from (
select time,company,quote-@quot as change, @quot:=quote curr_quote
from stocks order by company,time) A
order by company,time desc) B where B.LATEST=1;

ネストは相互に関連していないため、(計算的に) 見た目ほど (構文的に) 悪くありません:)

これについて何か助けが必要な場合はお知らせください。

于 2012-07-03T17:46:41.937 に答える
8

望ましい結果を得るには、まず、各企業の最後のタイムスタンプとその次のタイムスタンプを見つける必要があります。次のクエリを使用すると、非常に簡単です。

SELECT c.company, c.mts, max(l.ts) AS lts
  FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
  LEFT JOIN cq l
    ON c.company = l.company AND c.mts > l.ts
 GROUP BY c.company, c.mts;

目的の結果を得るには、このサブクエリを元のテーブルに結合する必要があります。

SELECT c.company, l.quote, coalesce(l1.quote, 0),
       (l.quote - coalesce(l1.quote, 0)) AS result
  FROM (SELECT c.company, c.mts, max(l.ts) AS lts
      FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
      LEFT JOIN cq l
        ON c.company = l.company AND c.mts > l.ts
     GROUP BY c.company, c.mts) AS c
  LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
  LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;

結果はSQL Fiddleで確認できます。

このクエリは標準の SQL 機能のみを使用しており、どの RDBMS でも機能するはずです。

于 2012-07-03T18:22:10.983 に答える