2012-05-23 127 views
1

我正在使用MSSQL 2008標準版計算sql中兩行兩次之間的差異

我在選擇命令中有多行填充事件。對於每一個我有一個時間戳的事件,我現在要計算事件之間的時間:

(number) | event   | timestamp   | duration 
---------+----------------+---------------------+---------- 
1  | logon   | 2012-05-23 10:00:00 | 
2  | incomming call | 2012-05-23 10:01:00 | 
3  | call ended  | 2012-05-23 10:02:00 | 
4  | logoff   | 2012-05-23 10:04:00 | 

(數列不存在,但它的解釋更容易),現在的時間單元第一行應爲1,第二行也爲1,第三行爲2.

有沒有人知道如何實現這個沒有循環等。

謝謝

+0

你確定你的意思是'MSSQL 2010'?沒有我知道的這樣的版本。 –

+0

對不起,2008當然是:-) – Philipp

回答

1

我發現比提供不太理想的CTE答案。我發現其他答案與聯合太複雜。我把這個問題解釋成這個片段

這裏是使用CTE的代碼,在CTE的select中創建一個序列,它通過一個有序的時間戳標識一個行號。生成的選擇選取生成的有序行並確定分鐘。

WITH AgentActions AS 
(
    select ROW_NUMBER() OVER (ORDER BY [TimeStamp]) -- Create an index number ordered by time. 
     AS [Sequence], 
    * from AgentInteractions 
) 
SELECT *, 
     ISNULL(DATEDIFF(Minute, 
         (SELECT other.TimeStamp 
           FROM AgentActions Other 
           WHERE other.Sequence = AgentActions.Sequence - 1), 
         AgentActions.TimeStamp), 
       0) 
    AS MinutesFromLastPoint 
FROM AgentActions; 

下面是設置表

CREATE TABLE AgentInteractions 
(
[Event]  VARCHAR(12) NOT NULL, 
[Timestamp] [DateTime] NOT NULL 
); 

INSERT INTO dbo.AgentInteractions(Event, TimeStamp ) 
VALUES ('Alpha', '1-Jan-2018 3:04:22 PM'), 
     ('Omega', '3-Jan-2018 10:04:22 PM'), 
     ('Beta', '2-Jan-2018 2:04:22 AM'); 

結果

enter image description here

SQL Fiddle Example

+0

謝謝你的回答,它的確看起來很好。我想知道爲什麼你要用子查詢來計算時間戳的差異,而不是像我自己的解決方案那樣加入連接。我比較了它,估計的執行計劃表示加入的版本是41%,子查詢是批量的59%。 – Philipp

+0

@Philipp有趣的結果...這是很好的記住。 – OmegaMan

+0

我會將您的答案設置爲解決方案,但是最終的連接將需要更改...(作爲可能需要其他人的信息) – Philipp

3

您需要自行加入。既然你需要生成一個ID,然後是這樣的:

select t1.*, datediff(minute, t2.timestamp, t1.timestamp) from 
    (select *, row_number() over (order by ...) as rowid from MyTable) t1 
inner join 
    (select *, row_number() over (order by ...) as rowid from MyTable) t2 
on t1.rowid = t2.rowid - 1 
+0

我需要改變一下這個問題:目前沒有id列,這只是一個數字列,使它更容易,你知道一種方法可能創建它它的選擇?這些事件不在同一個工會的兩個表中 – Philipp

+0

您可以將結果放入臨時表中,該表具有自動生成的ID列,然後自行加入。你也可以看看在(...)上使用row_number()。 – Phil

+0

@PhilippMehrwald:更新的答案 – Phil

1

這是我目前的版本/解決方案:

declare @temp table 
(
    id int, 
    timestamp datetime, 
    type nvarchar(255), 
    skillname nvarchar(255), 
    event nvarchar(255), 
    userstatus nvarchar(255) 
) 

insert into @temp (id, timestamp, type, skillname, event, userstatus) 
(
    select ROW_NUMBER() over (order by timestamp) as id, * from 
    (
     select TimeStamp, 'Event' as type, SkillName, Event, UserStatus from AgentEvents 
      where TimeStamp >= '2012-05-22T00:00:00' 
       and UserName like '%engel%' 
     union 
     select TimeStamp, 'Anruf' as type, SkillName, '' as event, '' as status from calls 
      where TimeStamp >= '2012-05-22T00:00:00' 
       and UserName like '%engel%' 
    ) as a 
) 

select t1.*, DATEDIFF(second, t1.timestamp, t2.timestamp) as duration 
from @temp t1 
left outer join @temp t2 on t1.id = t2.id - 1 

編輯:改變inner joinleft outer join,否則最後一行會丟失。

0

據我所知,你需要更新持續時間欄。

您可以使用這樣的事情:

update mytable a set duration = DateDiff(a.timestamp, select top b.timestamp from mytable b order by b.timestamp asc) 

我不能測試,但只給你一個想法(它可能有一些語法錯誤)。 使用'top'和'order by'子句應該可以做到這一點。

(編輯)

+0

select top將只適用於SQLServer而不是其他任何數據庫 – richardtz

0

我想你最好,因爲它不報告的第一行創建觸發器

CREATE TRIGGER update_duration ON sometable 
INSTEAD OF INSERT 
AS 
DECLARE @lastDT datetime 
BEGIN 
SET @lastDT = 
    (SELECT TOP 1 _timestamp 
    FROM sometable 
    ORDER BY _timestamp DESC) 
UPDATE sometable 
SET duration = DATEDIFF(MINUTE, @lastDT, GETDATE()) 
END 
+0

我使用'union'將2個表放在一起,觸發器無法選擇。 – Philipp

0

WITH rows AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY Col1) AS rn FROM dbo.Table_2 ) SELECT mc.col1, DATEDIFF(HOUR, mc.Col1, mp.Col1) as TimeDiffInHours FROM rows mc JOIN rows mp ON mc.rn = mp.rn-1

+0

由於'mc.rn = mp.rn-1',導致數據不報告第一行,它不能匹配第1行。 – OmegaMan