选择列值已更改的行: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中文网其他相关文章!