1

我正在使用 MSSQL 2008 标准

我在选择命令中有多行,其中填充了事件。对于每个事件我都有一个时间戳,现在我想计算事件之间的时间:

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

有谁知道如何在没有循环等的情况下实现这一目标。

谢谢

4

6 回答 6

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
于 2012-05-23T09:39:28.360 回答
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,否则最后一行将丢失。

于 2012-05-23T10:57:52.847 回答
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' );

结果

在此处输入图像描述

SQL Fiddle Example

于 2015-07-07T15:36:42.377 回答
0

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

你可以使用这样的东西:

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

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

(已编辑)

于 2012-05-23T11:10:30.430 回答
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
于 2012-05-23T11:30:07.493 回答
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

于 2014-06-10T12:39:07.457 回答