在sql中计算两行中两次的差异

时间:2012-05-23 09:36:27

标签: sql-server

我正在使用MSSQL 2008 Standard

我在select命令中有多行,这些行充满了事件。对于每个事件我都有一个时间戳,现在我想计算事件之间的时间:

(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。

有没有人知道如何在没有循环的情况下实现这一点等等。

谢谢

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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 join更改为left outer join,否则最后一行将丢失。

答案 2 :(得分:1)

由于没有报告第一行,我发现提供的CTE答案不太理想。我发现连接的其他答案太复杂了。我将问题提炼到这个片段

以下是使用CTE的代码,在CTE的选择中创建一个序列,该序列通过有序时间戳标识行号。结果选择选择生成的有序行并确定分钟。

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

答案 3 :(得分:0)

据我了解,您需要更新持续时间列。

您可以使用以下内容:

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

我无法测试它,只是为了给你一个想法(它可能有一些语法错误)。 使用'top'和'order by'子句应该可以解决问题。

(编辑)的

答案 4 :(得分: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

答案 5 :(得分: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