| 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
これは私のお気に入りの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
は、現在の行の引用符の値を保持します。ノート:
order by
句は、通常のウィンドウ関数の場合と同様にここで重要です。company
の引用符の違いを確実に計算するために、company
にラグを使用することもできます。@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;
ネストは相互に関連していないため、(計算上)見た目ほど(構文的に)悪くはありません:)
これに関して何か助けが必要な場合はお知らせください。
MySQL 8.0以降では、LAG
をシミュレートする必要はありません。ネイティブにサポートされていますが、
ウィンドウ関数 :
パーティション内の現在の行からN行だけ遅れる(先行する)行からexprの値を返します。そのような行がない場合、戻り値はデフォルトです。たとえば、Nが3の場合、戻り値は最初の2行のデフォルトです。 Nまたはデフォルトが欠落している場合、デフォルトはそれぞれ1およびNULLです。
SELECT
company,
quote,
LAG(quote) OVER(PARTITION BY company ORDER BY time) AS prev_quote
FROM tab;
目的の結果を得るには、まず各企業の最後のタイムスタンプと最後から2番目のタイムスタンプを見つける必要があります。次のクエリを使用すると、非常に簡単です。
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でも機能するはずです。