簡體   English   中英

計算行之間的時差

[英]Calculate time difference between rows

我目前有以下格式的數據庫

ID  |  DateTime             |  PID   |  TIU
1   |  2013-11-18 00:15:00  |  1551  |  1005
2   |  2013-11-18 00:16:03  |  1551  |  1885
3   |  2013-11-18 00:16:30  |  9110  |  75527
4   |  2013-11-18 00:22:01  |  1022  |  75
5   |  2013-11-18 00:22:09  |  1019  |  1311
6   |  2013-11-18 00:23:52  |  1022  |  89
7   |  2013-11-18 00:24:19  |  1300  |  44433
8   |  2013-11-18 00:38:57  |  9445  |  2010

我有一種情況,我需要使用DateTime列識別超過5分鍾的流程中的差距。

我要實現的一個示例是:

ID  |  DateTime             |  PID   |  TIU
3   |  2013-11-18 00:16:30  |  9110  |  75527
4   |  2013-11-18 00:22:01  |  1022  |  75
7   |  2013-11-18 00:24:50  |  1300  |  44433
8   |  2013-11-18 00:38:57  |  9445  |  2010

ID3是6分鍾1秒間隔之前的最后一行,ID4是它之后的下一行。
ID7是14分鍾7秒間隔之前的最后一行,ID8是下一個可用記錄。

我正在嘗試在SQL中執行此操作,但是如果需要,我可以在C#中進行處理。

我嘗試了許多內部聯接,但是表超過了300萬行,因此性能受到很大影響。

這是一個CTE解決方案,但是,正如已經指出的那樣,這可能並不總是很好-因為我們必須根據DateTime列計算函數,所以大多數索引將是無用的:

declare @t table (ID int not null,[DateTime] datetime not null,
                  PID int not null,TIU int not null)
insert into @t(ID,[DateTime],PID,TIU) values
(1,'2013-11-18 00:15:00',1551,1005  ),
(2,'2013-11-18 00:16:03',1551,1885  ),
(3,'2013-11-18 00:16:30',9110,75527 ),
(4,'2013-11-18 00:22:01',1022,75    ),
(5,'2013-11-18 00:22:09',1019,1311  ),
(6,'2013-11-18 00:23:52',1022,89    ),
(7,'2013-11-18 00:24:19',1300,44433 ),
(8,'2013-11-18 00:38:57',9445,2010  )

;With Islands as (
    select ID as MinID,[DateTime],ID as RecID from @t t1
    where not exists
        (select * from @t t2
            where t2.ID < t1.ID and --Or by date, if needed
                    --Use 300 seconds to avoid most transition issues
            DATEDIFF(second,t2.[DateTime],t1.[DateTime]) < 300
        )
    union all
    select i.MinID,t2.[DateTime],t2.ID
    from Islands i
        inner join
        @t t2
            on
                i.RecID < t2.ID and
                DATEDIFF(second,i.[DateTime],t2.[DateTime]) < 300
), Ends as (
    select MinID,MAX(RecID) as MaxID from Islands group by MinID
)
select * from @t t
where exists(select * from Ends e where e.MinID = t.ID or e.MaxID = t.ID)

這還會返回ID為1的行,因為該行在5分鍾之內沒有前一行-但是如果需要的話,應該很容易將其排除在最終選擇之外。

我假設我們可以使用ID作為增加日期的代理-如果兩行的ID在第二行中較高,則DateTime也將稍后。


Islands是遞歸的CTE。 上半部分(錨點)僅選擇在5分鍾之內沒有任何前一行的行。 我們為這些行選擇兩次ID ,並保留DateTime

在遞歸部分,我們試圖找到可以“上添加”到現有的表中的新行Islands行-在此基礎上新行比島的當前終點不超過5分鍾后。

遞歸完成后,我們將排除CTE產生的中間行。 例如,對於“ 4”島,它生成了以下行:

4,00:22:01,4
4,00:22:09,5
4,00:23:52,6
4,00:24:19,7

而我們關心的是最后一行,我們已經確定了從ID 4到ID 7的時間“孤島”-這就是第二個CTE( Ends )為我們找到的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM