2009-07-16 130 views
3

连续行假设表格如下:GROUP BY在SQL

 
ID State Date 
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 

问:
我怎么能集团通过现场“国家”,同时仍然保持状态的变化之间的边界?

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

结果如下:

 
ID State Date    Count 
12 1  2009-07-16 10:00 4 
45 2  2009-07-16 13:00 2 


但预计:

 
ID State Date    Count 
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这可能吗?我没有找到一个解决方案至今...

回答

8
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'); 
+0

真棒一个更长的描述,它只是工作。 – Kaii 2009-07-16 10:33:03

0

我可能会说明明显在这里,但如果你愿意利用Transact-SQL,你可以遍历表中的行并构建你自己的结果集,这可能看起来像一个麻烦,但它肯定会工作。迭代可以完成without the use of cursors

2

这是如何与热膨胀系数做MSSQL服务器上

-- 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 
+0

因为这是MySQL相关的,我没有任何MS SQL服务器,我无法测试你的代码。 反正..谢谢你的努力和你的贡献,它会帮助其他有类似问题的人。 – Kaii 2009-07-16 10:51:18

1

Here是像由Quassnoi提供的一个解决方案是如何工作的