SQL Server - 计算数据集中属性更改的次数(非并发)
Posted
技术标签:
【中文标题】SQL Server - 计算数据集中属性更改的次数(非并发)【英文标题】:SQL Server - Counting number of times an attribute in a dataset changes (non-concurrently) 【发布时间】:2011-02-17 08:57:10 【问题描述】:我有一个查询,它根据给定日期是否发生事件返回 1 或 0。这是按日期排序的。基本上,一个简单的结果集是:
Date | Type
---------------------
2010-09-27 1
2010-10-11 1
2010-11-29 0
2010-12-06 0
2010-12-13 1
2010-12-15 0
2010-12-17 0
2011-01-03 1
2011-01-04 0
我现在希望能够做的是计算单独的、非并发的 '0 实例的数量 - 即计算出现了多少个不同的 0 组。
在上面的例子中,答案应该是 3(一组 2,然后是另一组 2,最后以 1 结束)。
希望以上示例说明了我想要达到的目的。我一直在寻找一段时间,但发现很难简洁地描述我在寻找什么,因此没有找到任何相关的东西。
提前致谢,
乔什
【问题讨论】:
【参考方案1】:您可以在 CTE 中为每一行指定一个数字。然后,您可以自行加入表以查找上一行。知道了上一行,就可以将上一行为1,当前行为0的次数相加。例如:
; with NumberedRows as
(
select row_number() over (order by date) as rn
, type
from YourTable
)
select sum(case when cur.type = 0 and IsNull(prev.type,1) = 1 then 1 end)
from NumberedRows cur
left join
NumberedRows prev
on cur.rn = prev.rn + 1
【讨论】:
不应该是左连接(因为您已经在使用 IsNull 因为您已经认识到第一行可能是 0) @Damien_The_Unbeliever:谢谢,已修复 太棒了,谢谢。我正在考虑类似的事情,但觉得它可能会过度弯曲关系模型 - 感觉有点程序化。这只是我必须走的路线吗?【参考方案2】:这是“岛屿”问题的变体。我的第一个答案使用 Itzik Ben Gan 的双重 row_number
技巧来有效地识别连续的数据组。 Type,Grp
的组合标识了数据中的每个独立岛。
You can read more about the different approaches to tackling this problem here.
;WITH T AS (
SELECT *,
ROW_NUMBER() OVER(ORDER BY Date) -
ROW_NUMBER() OVER(PARTITION BY Type ORDER BY Date) AS Grp
FROM YourTable
)
SELECT COUNT(DISTINCT Grp)
FROM T
WHERE Type=0
我的第二个答案需要一次通过数据。它不能保证有效,但与许多人成功用于连接字符串而不会出现问题的技术原理相同。
DECLARE @Count int = 0
SELECT @Count = CASE WHEN Type = 0 AND @Count <=0 THEN -@Count+1
WHEN Type = 1 AND @Count > 0 THEN - @Count
ELSE @Count END
FROM YourTable
ORDER BY Date
SELECT ABS(@Count)
【讨论】:
【参考方案3】:看看这个例子,使用 Sql Server 2005+
DECLARE @Table TABLE(
Date DATETIME,
Type INT
)
INSERT INTO @Table SELECT '2010-09-27',1
INSERT INTO @Table SELECT '2010-10-11',1
INSERT INTO @Table SELECT '2010-11-29',0
INSERT INTO @Table SELECT '2010-12-06',0
INSERT INTO @Table SELECT '2010-12-13',1
INSERT INTO @Table SELECT '2010-12-15',0
INSERT INTO @Table SELECT '2010-12-17',0
INSERT INTO @Table SELECT '2011-01-03',1
INSERT INTO @Table SELECT '2011-01-04',0
;WITH Vals AS (
SELECT *,
ROW_NUMBER() OVER(ORDER BY Date) ROWID
FROM @Table
)
SELECT v.*
FROM Vals v LEFT JOIN
Vals vNext ON v.ROWID + 1 = vNext.ROWID
WHERE v.Type = 0
AND (vNext.Type = 1 OR vNext.Type IS NULL)
【讨论】:
+1,应该是SELECT COUNT...
吧?因为这就是 OP 所追求的。
是的,只是想显示查询的详细信息。以上是关于SQL Server - 计算数据集中属性更改的次数(非并发)的主要内容,如果未能解决你的问题,请参考以下文章