【问题标题】:SQL Server - Counting number of times an attribute in a dataset changes (non-concurrently)SQL Server - 计算数据集中属性更改的次数(非并发)
【发布时间】: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 结束)。

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

提前致谢,

乔什

【问题讨论】:

    标签: sql sql-server tsql subquery gaps-and-islands


    【解决方案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 所追求的。
      • 是的,只是想显示查询的详细信息。
      猜你喜欢
      • 2015-01-05
      • 1970-01-01
      • 2019-06-06
      • 2020-07-06
      • 1970-01-01
      • 2020-09-09
      • 2010-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多