4

我有一个查询,它根据给定日期是否发生事件返回 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(1 组 2,然后是另一组 2,最后以 1 结束)。

希望上面的示例说明了我想要达到的目的。我一直在寻找一段时间,但发现很难简洁地描述我在寻找什么,因此没有找到任何相关的东西。

提前致谢,

乔什

4

3 回答 3

3

您可以在 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
于 2011-02-17T09:04:47.067 回答
2

这是“岛屿”问题的变体。我的第一个答案使用 Itzik Ben Gan 的双重row_number技巧来有效地识别连续的数据组。的组合Type,Grp标识数据中的每个单独的岛屿。

您可以在此处阅读有关解决此问题的不同方法的更多信息。

;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)
于 2011-02-17T09:32:36.277 回答
1

看看这个例子,使用 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)
于 2011-02-17T09:06:19.140 回答