列の値が変更された行の選択: SQL テクニック
列の値が遷移するインスタンスを決定することは、さまざまな操作において重要な操作です。データ分析シナリオ。この記事では、テーブル内のそのような変更を効率的に識別するための手法について説明します。
問題ステートメント
「値」列と「時間」列を含む次のテーブルについて考えてみましょう。
Value | Time | |
---|---|---|
0 | 15/06/2012 8:03:43 PM | |
1 | 15/06/2012 8:03:43 PM | * |
1 | 15/06/2012 8:03:48 PM | |
1 | 15/06/2012 8:03:53 PM | |
1 | 15/06/2012 8:03:58 PM | * |
2 | 15/06/2012 8:04:03 PM | * |
2 | 15/06/2012 8:04:08 PM | |
3 | 15/06/2012 8:04:13 PM | * |
3 | 15/06/2012 8:04:18 PM | |
3 | 15/06/2012 8:04:23 PM | |
2 | 15/06/2012 8:04:28 PM | * |
2 | 15/06/2012 8:04:33 PM |
このタスクは、「値」の遷移を示す「*」でマークされた行を識別することです。
解決策
ウィンドウ関数の使用 (SQL Server 2012 以降)
SQL Server で導入されたウィンドウ関数を使用する2012 では、この操作を実行できます効率的に:
;WITH x AS ( SELECT value, time, rn = ROW_NUMBER() OVER (PARTITION BY Value ORDER BY Time) FROM dbo.table ) SELECT * FROM x WHERE rn = 1;
このクエリは、「Value」の各パーティション内の行番号を計算し、各パーティションの最初の行 (rn = 1) を選択します。
テーブル結合の使用(SQL Server 2008 以前)
2012 より前の SQL Server バージョンの場合、次のとおりです。次のアプローチを使用できます。
DECLARE @x TABLE(value INT, [time] DATETIME) INSERT @x VALUES (0,'20120615 8:03:43 PM'),-- (1,'20120615 8:03:43 PM'),--* (1,'20120615 8:03:48 PM'),-- (1,'20120615 8:03:53 PM'),-- (1,'20120615 8:03:58 PM'),-- (2,'20120615 8:04:03 PM'),--* (2,'20120615 8:04:08 PM'),-- (3,'20120615 8:04:13 PM'),--* (3,'20120615 8:04:18 PM'),-- (3,'20120615 8:04:23 PM'),-- (2,'20120615 8:04:28 PM'),--* (2,'20120615 8:04:33 PM'); ;WITH x AS ( SELECT *, rn = ROW_NUMBER() OVER (ORDER BY time) FROM @x ) SELECT x.value, x.[time] FROM x LEFT OUTER JOIN x AS y ON x.rn = y.rn + 1 AND x.value <> y.value WHERE y.value IS NOT NULL;
このクエリはテーブルに対して自己結合を実行し、隣接する行を比較して値の変更を特定します。中間結果を保存するには別のテーブル変数が必要です。
注: ウィンドウ関数はパフォーマンスが向上しますが、SQL Server のすべてのバージョンで使用できるわけではありません。バージョンとパフォーマンス要件に最も適したアプローチを選択してください。
以上がSQL で列の値が変更される行を効率的に特定するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。