【问题标题】:GROUP BY for continuous rows in SQLGROUP BY 用于 SQL 中的连续行
【发布时间】:2010-11-11 07:37:33
【问题描述】:

给定下表:

身份证件日期 12 1 2009-07-16 10:00 45 2 2009-07-16 13:00 67 2 2009-07-16 14:40 77 1 2009-07-16 15:00 89 1 2009-07-16 15:30 99 1 2009-07-16 16:00

问题:
如何按字段“状态”进行 GROUP,同时仍保持状态更改之间的边界?

SELECT MIN(ID) AS ID, State, MIN(Date) AS Date, COUNT(ID) AS Count
FROM table GROUP BY State

结果如下:

ID 状态日期计数 12 1 2009-07-16 10:00 4 45 2 2009-07-16 13:00 2

但这是所需的输出:

ID 状态日期计数 12 1 2009-07-16 10:00 1 45 2 2009-07-16 13:00 2 77 1 2009-07-16 15:00 3
这在 SQL 中可能吗?到目前为止我还没有找到解决方案...

【问题讨论】:

    标签: mysql grouping gaps-and-islands


    【解决方案1】:

    我在这里可能会说显而易见的,但如果您愿意使用 Transact-SQL,您可以遍历表的行并构建自己的结果集,这可能看起来很麻烦,但肯定会工作。迭代可以完成without the use of cursors

    【讨论】:

      【解决方案2】:

      Here 详细描述了 Quassnoi 提供的解决方案的工作原理

      【讨论】:

        【解决方案3】:

        这是在 MSSQL 服务器上使用 CTE 的方法

        -- DROP TABLE MyLog
        CREATE TABLE MyLog(
                ID          INT PRIMARY KEY
                , State     INT
                , Date      DATETIME
                )
        INSERT MyLog
        SELECT 12, 1, '2009-07-16 10:00' UNION ALL
        SELECT 45, 2, '2009-07-16 13:00' UNION ALL
        SELECT 67, 2, '2009-07-16 14:40' UNION ALL
        SELECT 77, 1, '2009-07-16 15:00' UNION ALL
        SELECT 89, 1, '2009-07-16 15:30' UNION ALL
        SELECT 99, 1, '2009-07-16 16:00'
        
        ;WITH   CTE
        AS      (
                SELECT  ROW_NUMBER() OVER(ORDER BY ID) AS RowNo
                        , *
                FROM    MyLog
                )
        , MyLogGroup
        AS      (
                SELECT  l.*
                        , ( SELECT  MAX(ID)
                            FROM    CTE c
                            WHERE   NOT EXISTS (SELECT * FROM CTE
                                                WHERE RowNo = c.RowNo-1 AND State = c.State)
                                    AND c.ID <= l.ID) AS GroupID
                FROM    MyLog l
                )
        SELECT  *
        FROM    MyLogGroup
        

        【讨论】:

        • 因为这是 mysql 相关的,我没有任何 MS SQL 服务器,我无法测试你的代码。无论如何..感谢您的努力和贡献,它将帮助其他有类似问题的人。
        【解决方案4】:
        SELECT  MIN(id) AS id, MIN(ts) AS ts, MIN(state) AS state, COUNT(*) cnt
        FROM    (
                SELECT  @r := @r + (@state != state) AS gn,
                        @state := state AS sn,
                        s.*
                FROM    (
                        SELECT  @r := 0,
                                @state := 0
                        ) vars,
                        t_state s
                ORDER BY
                        ts
                ) q
        GROUP BY
                gn
        

        用于测试的表创建脚本:

        CREATE TABLE t_state (id INT NOT NULL PRIMARY KEY, state INT NOT NULL, ts DATETIME NOT NULL);
        
        INSERT
        INTO  t_state
        VALUES
        (12,   1,      '2009-07-16 10:00'),
        (45,   2,      '2009-07-16 13:00'),
        (67,   2,      '2009-07-16 14:40'),
        (77,   1,      '2009-07-16 15:00'),
        (89,   1,      '2009-07-16 15:30'),
        (99,   1,      '2009-07-16 16:00');
        

        【讨论】:

        • 我有相同的用例,但还有另一列,我想按该列分组,并希望为该列的每个值获得相同的结果。知道如何做到这一点吗?
        • @AnkitGupta 请将其作为另一个问题发布。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-20
        • 1970-01-01
        • 2019-01-16
        • 2011-02-07
        • 1970-01-01
        • 2023-04-07
        相关资源
        最近更新 更多