2010-04-21 31 views
2

我有一个表基本上像这样获得行的集群并拢时刻

ID | ItemID |  Start  |   End  | 
--------------------------------------------------------------- 
    1  234  10/20/09 8:34:22  10/20/09 8:35:10 
    2  274  10/20/09 8:35:30  10/20/09 8:36:27 
    3  272  10/21/09 12:15:00  10/21/09 12:17:00 
    4  112  10/21/09 12:20:14  10/21/09 12:21:21 
    5  15  10/21/09 12:22:39  10/21/09 12:24:15 

有两个条目的“簇”在这里,1-2和3-5通过在时间上的间隙分开,具体地> 30分钟是我感兴趣的。

我想要的是条目集群的第一行和最后一行。这很容易通过检索所有行并按照开始时间循环来实现,但是如果可能的话,我希望在SQL中使用它。

我正在使用SQL Server 2008,谢谢。

编辑:

每一行都将包含

first.* , last.* 

,其中第一个是集群中的第一排和最后一个是最后一行。

该表的结果将是

1  234  10/20/09 8:34:22  10/20/09 8:35:10   2  274  10/20/09 8:35:30  10/20/09 8:36:27 
    3  272  10/21/09 12:15:00  10/21/09 12:17:00   5  15  10/21/09 12:22:39  10/21/09 12:24:15 
+0

什么*确切*的结果集,你会喜欢吗? – gbn 2010-04-21 03:47:25

回答

3

尝试了这一点:

DECLARE @YourTable table (ID int, ItemID int, StartD datetime, EndD datetime) 
INSERT @YourTable VALUES (1,234,'10/20/09 8:34:22' ,'10/20/09 8:35:10') 
INSERT @YourTable VALUES (2,274,'10/20/09 8:35:30' ,'10/20/09 8:36:27') 
INSERT @YourTable VALUES (3,272,'10/21/09 12:15:00','10/21/09 12:17:00') 
INSERT @YourTable VALUES (4,112,'10/21/09 12:20:14','10/21/09 12:21:21') 
INSERT @YourTable VALUES (5,15 ,'10/21/09 12:22:39','10/21/09 12:24:15') 

;WITH AggValues AS 
(SELECT 
    MAX(ID) AS MaxID, COUNT(ID) AS CountOf, MIN(ID) AS MinID 
    FROM @YourTable 
) 
, NumberRows AS 
(SELECT --generate a first row to help get a range 
    0 AS ID, a.StartD-1 AS StartD, a.EndD-1 AS EndD, 0 AS RowNumber 
    FROM @YourTable a 
     INNER JOIN AggValues dt ON a.ID=dt.MinID 
UNION 
SELECT --get all actual rows 
    ID, StartD, EndD, ROW_NUMBER() OVER(ORDER BY ID) AS RowNumber 
    FROM @YourTable 
UNION 
SELECT --generate a last row to help get a range 
    dt2.MaxID+1 AS ID, a.StartD+1 AS StartD, a.EndD+1 AS EndD, dt2.CountOf+1 AS RowNumber 
    FROM @YourTable a 
     INNER JOIN AggValues dt2 ON a.ID=dt2.MaxID 
) 
, FindGaps AS 
(SELECT 
    a.ID,DATEDIFF(minute,b.StartD,a.EndD) AS Diff, a.RowNumber, c.RowNumber AS PreviousRowNumber 
    FROM NumberRows     a 
     LEFT OUTER JOIN NumberRows b ON a.RowNumber=b.RowNumber+1 
     LEFT OUTER JOIN NumberRows c ON a.RowNumber-1=c.RowNumber 
) 
, Gaps AS 
(SELECT 
    f.ID,f.RowNumber, f.PreviousRowNumber, ROW_NUMBER() OVER(ORDER BY ID) AS GapRowNumber 
    FROM FindGaps f 
    WHERE f.Diff>30 
) 
, Results AS 
(SELECT 
    g.ID,n.ID AS IDEnd 
    FROM Gaps      g 
     LEFT OUTER JOIN Gaps  x ON g.GapRowNumber+1=x.GapRowNumber 
     LEFT OUTER JOIN NumberRows n ON x.PreviousRowNumber=n.RowNumber 
    WHERE n.ID IS NOT NULL 
) 
SELECT 
    a.*,b.* 
    from Results      r 
     LEFT OUTER JOIN @YourTable a ON r.ID=a.ID 
     LEFT OUTER JOIN @YourTable b ON r.IDEnd=b.ID 

OUTPUT:

ID   ItemID  StartD     EndD     ID   ItemID  StartD     EndD 
----------- ----------- ----------------------- ----------------------- ----------- ----------- ----------------------- ----------------------- 
1   234   2009-10-20 08:34:22.000 2009-10-20 08:35:10.000 2   274   2009-10-20 08:35:30.000 2009-10-20 08:36:27.000 
3   272   2009-10-21 12:15:00.000 2009-10-21 12:17:00.000 5   15   2009-10-21 12:22:39.000 2009-10-21 12:24:15.000 

(2 row(s) affected) 
+0

很好,谢谢 – Mike 2010-04-21 17:25:02