2011-06-22 81 views
3

我在编写查询时遇到困难。我需要将时间连续的状态行合并成一个状态。例如,给定数据:当一个的结束时间是另一个的开始时间时合并行

start     end      state seconds 
2011-04-21 08:13:30.000 2011-04-21 08:18:00.000 STATE1 270 
2011-04-21 08:18:00.000 2011-04-21 08:22:30.000 STATE1 270 
2011-04-21 08:22:30.000 2011-04-21 08:26:26.000 STATE1 236 
2011-04-21 08:26:26.000 2011-04-21 08:26:47.000 STATE2 21 
2011-04-21 08:26:47.000 2011-04-21 08:27:30.000 STATE3 43 
2011-04-21 08:27:30.000 2011-04-21 08:28:20.000 STATE1 50 
2011-04-21 08:40:30.000 2011-04-21 08:41:00.000 STATE1 30 

我需要结合起来,只有当row2.state = row1.state AND row2.start = row1.end行并拿出状态的全面启动和结束时间。结果应该是:

start     end      state seconds 
2011-04-21 08:13:30.000 2011-04-21 08:26:26.000 STATE1 776 
2011-04-21 08:26:26.000 2011-04-21 08:26:47.000 STATE2 21 
2011-04-21 08:26:47.000 2011-04-21 08:27:30.000 STATE3 43 
2011-04-21 08:27:30.000 2011-04-21 08:28:20.000 STATE1 50 
2011-04-21 08:40:30.000 2011-04-21 08:41:00.000 STATE1 30 

这里是例如SQL:

CREATE TABLE Data (
    ID int IDENTITY(1,1) not null, 
    Date DateTime not null, 
    State nvarchar(40) not null, 
    Seconds int not null, 
    PRIMARY KEY(ID) 
); 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:13:30.000', 'STATE1', 270) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:18:00.000', 'STATE1', 270) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:22:30.000', 'STATE1', 236) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:26:26.000', 'STATE2', 21) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:26:47.000', 'STATE3', 43) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:27:30.000', 'STATE1', 50) 
INSERT INTO Data(Date,State,Seconds) VALUES('2011-04-21 08:40:30.000', 'STATE1', 30) 

SELECT Date as 'start', DATEADD(s,Seconds,Date) as 'end', State, Seconds FROM Data 

提前感谢!

回答

4

试试这个(> =的SQL Server 2005):

WITH qry AS 
(
    SELECT a.* 
        ,ROW_NUMBER() OVER (ORDER BY [start]) rn 
    FROM (SELECT Date as 'start', DATEADD(s,Seconds,Date) as 'end', State, Seconds FROM Data) a 
) 
SELECT DISTINCT MIN(a.start) OVER(PARTITION BY a.State, a.[end] - ISNULL(b.start, a.start)) , 
       MAX(a.[end]) OVER(PARTITION BY a.State, a.[end] - ISNULL(b.start, a.start)) , 
       a.state 
       ,SUM(a.Seconds) OVER(PARTITION BY a.State, a.[end] - ISNULL(b.start, a.start)) 

    FROM qry a LEFT JOIN qry b 
     ON a.rn + 1 = b.rn 
    AND a.[end] = b.start 
+0

完美!这是一个惊人的SQL。谢谢你的时间。 – Blazes

+0

该解决方案似乎有一个错误。我已经改变了一些数据,如[这里]所示(https://gist.github.com/2205609)。然后当我运行你的答案的SQL时,我得到了不正确的结果。这似乎是因为您使用'a。[end] - ISNULL(b.start,a.start))'来划分最终结果,但这在不止一个组的情况下是不正确的,就像我的样品。 – VitalyB

+0

5年后,从谷歌到这里,看不到'OVER(PARTITION by a。[end] - ISNULL(b.start,a.start))'可以工作 – OGHaza

0

使用下面的提示:

SELECT 
    T1.StartDate, 
    T2.EndDate 
FROM 
    MyTable T1 
INNER JOIN 
    MyTable T2 
    ON T1.Status = T2.Status AND 
    T1.EndDate = T2.StartDate 
+0

我不认为就是这样 - 它只会选择一行的结尾是另一行的起点的行。我需要所有的行,但连续的状态是合并的。 – Blazes

+0

@Blazes:很容易投票,难以阅读和吹牛是必须的!你错过了阅读答案的第一行中的“提示”一词! –

0

试试这个:

SELECT d1.Date as 'start', d2.Date as 'end', d1.State,SUM(d1.Seconds) FROM Data d1,Data d2 
where 
convert(varchar(5),d1.Date,8) = convert(varchar(5),DATEADD(s,d2.Seconds,d2.Date),8) 
AND 
d1.State = d2.State 
group by d1.Date,d1.State,d2.Date 
相关问题