【问题标题】:How to GROUP BY data in following method in SQL Server? Gaps and Islands如何在 SQL Server 中按以下方法对数据进行 GROUP BY?差距和岛屿
【发布时间】:2017-11-06 10:39:32
【问题描述】:
DECLARE @Table TABLE 
               (
                    Col_status VARCHAR(5),
                    Col_Location VARCHAR(5),     
                    Col_NUM INT
               )

INSERT INTO @Table (Col_status, Col_Location, Col_NUM)
VALUES ('ON', 'AAA', 1), ('ON', 'AAA', 2),
       ('OFF', 'AAA', 3), ('ON', 'BBB', 4),
       ('ON', 'BBB', 5), ('ON', 'CCC', 6), ('ON', 'BBB', 7),
       ('OFF', 'AAA', 9), ('OFF', 'AAA', 10);

SELECT *
FROM @Table

输出:

Col_status  Col_Location    Col_NUM
----------  ------------    -------
ON          AAA             1
ON          AAA             2
OFF         AAA             3
ON          BBB             4
ON          BBB             5
ON          CCC             6
ON          BBB             7
OFF         AAA             9
OFF         AAA            10

但我希望得到以下答案;我大部分时间都花在这上面。

  • 按第一列和第二列分组,但应根据第三列值的顺序进行拆分

输出应该是这样的:

Col_status  Col_Location    Min(Col_NUM)    count(Col_NUM)
---------- -------------    -------------   --------------
ON          AAA             1               2
OFF         AAA             3               1
ON          BBB             4               2
ON          CCC             6               1
ON          BBB             7               1
OFF         AAA             9               2

感谢和问候,卡西尔 M

【问题讨论】:

    标签: sql sql-server tsql group-by


    【解决方案1】:

    这是一个孤岛和缺口问题。可以这样解决:

    select t.Col_status,t.Col_Location, min(t.col_num), count(*)
    from
    (
       select t.*, row_number() over (partition by Col_status,Col_Location order by Col_NUM) group_rn
       from @Table t
    ) t
    group by t.Col_status,t.Col_Location, t.col_num - t.group_rn
    

    demo

    基本思想在t.col_num - t.group_rn中,其中相同序列中的行(具有连续的id)具有相同的这种差异结果。因此,t.col_num - t.group_rn 允许您隔离这些序列并正确地进行分组。

    【讨论】:

    • 没有关于为什么会这样的信息,但话又说回来,OP 也没有关于他的逻辑的信息......所以我还是给你了
    • @GuidoG 添加:)
    【解决方案2】:

    正如之前的回答所提到的,这是一个差距和孤岛问题。

    所以你需要创建一个会生成岛屿的查询,所以这个例子,这里是一个

    ;WITH cteX
    AS(
       SELECT TOP 100 PERCENT
              t.Col_NUM
            , t.Col_Location
            , t.Col_status
            , RN = ROW_NUMBER() OVER (PARTITION BY Col_status,Col_Location ORDER BY Col_NUM) 
       FROM @Table t
       ORDER BY t.Col_NUM
    )
    SELECT
          X.Col_NUM
        , X.Col_Location
        , X.Col_status
        , X.RN
        , Island = X.Col_NUM - X.RN
    FROM
        cteX X
    ORDER BY
        X.Col_NUM - X.RN
    

    输出显示群岛

    所以使用这个查询你可以得到你想要的结果

    ;WITH cteX
    AS(
       SELECT TOP 100 PERCENT
              t.Col_NUM
            , t.Col_Location
            , t.Col_status
            , RN = ROW_NUMBER() OVER (PARTITION BY Col_status,Col_Location ORDER BY Col_NUM) 
       FROM @Table t
       ORDER BY t.Col_NUM
    )
    
    SELECT
          X.Col_status
        , X.Col_Location
        , MIN_Col_Num   = MIN(X.Col_NUM)
        , COUNT_Col_NUM = COUNT(*)
    FROM cteX X
    GROUP BY
          X.Col_Location
        , X.Col_status
        , (X.Col_NUM - X.RN)
    ORDER BY
       MIN_Col_Num,,(X.Col_NUM - X.RN)
    

    输出

    【讨论】:

      【解决方案3】:

      试试这个:

      DECLARE @Table TABLE (
       Col_status varchar(5),
            Col_Location varchar(5),     
            Col_NUM INT
      )
      
      INSERT INTO @Table (Col_status,Col_Location,Col_NUM)
            VALUES ('ON','AAA',1),('ON','AAA',2),('OFF','AAA',3),('ON','BBB',4),
      ('ON','BBB',5),('ON','CCC',6),('ON','BBB',7),('OFF','AAA',9),('OFF','AAA',10);
      
      select A.Col_status,A.Col_Location
          ,MIN(A.col_num)[Min(Col_NUM)]
          ,COUNT(1)[count(Col_NUM)]
      FROM
      (
         SELECT t.*
          ,ROW_NUMBER() OVER (PARTITION BY Col_status,Col_Location ORDER BY Col_NUM) RN
         FROM @Table t
      ) A
      group by A.Col_status,A.Col_Location, A.col_num - A.RN
      ORDER BY min(A.col_num)
      

      【讨论】:

        【解决方案4】:

        你能不能只将结果选择到一个临时表中然后这样做:

        SELECT Col_Location, 
               Col_Status, 
               MIN (Col_Num), 
               COUNT(*) AS Count(Col_NUM) 
        FROM #TMP
        GROUP BY Col_Location, 
                 Col_Status
        ORDER BY 1, 2
        

        【讨论】:

        • 它没有返回 OP 请求的结果
        【解决方案5】:

        在这种情况下,您需要按两列分组 :) 试试这个查询:

        SELECT Col_status, Col_Location, MIN(Col_NUM), COUNT(Col_NUM)
        FROM @Table
        GROUP BY Col_status, Col_Location
        

        【讨论】:

        • 它没有返回操作请求的结果
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多