【问题标题】:SQL Server 2008 Query to Calculate Total Time Between Successive EventsSQL Server 2008 查询以计算连续事件之间的总时间
【发布时间】:2015-10-21 18:01:46
【问题描述】:

我希望能够计算 SQL Server 2008 中某些事件之间的总时间。

我有一张如下表:

UserId   Event      EventTimestamp
+-------+----------+---------------+
 1       CheckedIn  14-05-15 10:01
 2       CheckedIn  14-05-15 10:15
 3       CheckedIn  14-05-15 10:17
 1       CheckedOut 14-05-15 10:25
 1       Logout     14-05-15 10:26

如果您查看表格,用户可以签入,然后可以签出,然后下线。

我想计算一个人从签到到签出点之间的时间,按每周分组,其中持续时间(签到和签出之间)小于 10 分钟。

到目前为止,我已经设法按周分组,但我似乎无法计算这些事件之间的持续时间(将按此顺序发生)...

select      
   'Week ' + cast(datepart(wk, EventUpdateStamp) as varchar(2)) Week,     
    UserId,
    Event 
from MyTable 
group by datepart(wk, EventUpdateStamp), UserId, Event 

我想要这样的结果:

UserId   TotalSessionCheckInTimeMinutes  WeekNumber   
+-------+------------------------------+---------------+
 1       24                             43

以第一行为例:

  • 1 是用户 ID
  • 24 是他之间的总持续时间(以分钟为单位) 入住和退房
  • 43 是一年中的第几周

我只想将入住加入退房。不想在签出和注销之间进行衡量(换句话说,衡量他签入的时间)。

【问题讨论】:

  • 你能解释一下这一行的结果吗:1 10 43? 10 表示 10:00?
  • SQL Server 2008 R2 版
  • 1 10 43: 1 是用户 ID,24 是他入住和退房之间的总时长,以分钟为单位,43 是一年中的周数。
  • @AshesToAshes:我认为第二行必须是:1 1 43(其中 1 是用户 ID,1 是签出和注销之间的差异,43 周数)。对吗?
  • 我们只想包含签入到签出,因此排除 1 1 20 结果,因为我们不想在签出和注销之间进行测量。 (意思是他在办公室呆了多久)

标签: sql-server tsql sql-server-2008-r2


【解决方案1】:

试试这个:

SELECT t1.UserId, 
    DATEDIFF(minute,
        t1.EventTimestamp,
        (SELECT MIN(t3.EventTimestamp)
        FROM MyTable t3
        WHERE t3.UserId = t1.UserId
        AND t3.EventTimestamp> t1.EventTimestamp)
    ), 
   CAST(DATEPART(wk, EventTimestamp) as varchar(2)) Week
FROM MyTable t1
WHERE EXISTS(
    SELECT 'NEXT'
    FROM MyTable t2
   WHERE t2.UserId = t1.UserId
   AND t2.EventTimestamp> t1.EventTimestamp
   AND t2.Event != 'Logout')

SqlFiddle

here

【讨论】:

  • 它给出了一个错误,说它不知道't'是什么。当我将 t.UserId 更改为 t1.UserId 时,我得到了结果,但它们都是负值。另外,我注意到您没有与事件进行比较?
  • 已修复。 t.UserId -> t1.UserId(我尝试使用 Sql Fiddle,但今天已关闭)
  • 是的,我无法让它在 SQL Fiddle 上运行,但它也不适合我 :(
  • 我在我的电脑上试过了。结果是:1 24 20 / 1 1 20
  • 对不起,我在您之前的评论中误解了您,我们只想将签入到签出,因此排除 1 1 20 结果,因为我们不想在签出和注销之间进行测量. (意思是他在办公室呆了多长时间)。
【解决方案2】:

你可以试试这个:

SELECT DISTINCT M.UserId, DATEPART(HOUR,A.TotalSessionCheckInTimeMinutes)*60 + DATEPART(MINUTE,A.TotalSessionCheckInTimeMinutes) AS TotalSessionCheckInTimeMinutes, DATEPART(WEEKDAY, M.EventTimestamp) FROM Mytable M
     CROSS APPLY (
        SELECT CAST((M1.EventTimestamp - M2.EventTimestamp) AS TIME) AS TotalSessionCheckInTimeMinutes
        FROM Mytable M1
          CROSS JOIN Mytable M2
            WHERE M1.Event = 'CheckOut' AND M2.Event = 'CheckIn' AND M1.UserId = M.UserId) AS A
UNION ALL
SELECT DISTINCT M.UserId, A.TotalSessionCheckInTimeMinutes, DATEPART(WEEKDAY, M.EventTimestamp) FROM Mytable M
     CROSS APPLY (
       SELECT CAST((M1.EventTimestamp - M2.EventTimestamp) AS TIME) AS TotalSessionCheckInTimeMinutes
       FROM Mytable M1
          CROSS JOIN Mytable M2
            WHERE M1.Event = 'LogOut' AND M2.Event = 'CheckIn' AND M1.UserId = M.UserId) AS A

【讨论】:

  • 似乎没有给出正确的数据,因为它在 TotalSessionCheckInTimeMinutes 中给出了 1899 年的日期和错误的周数。
  • 我认为我的代码存在问题:M1.EventTimestamp - M2.EventTimestamp。您可以使用转换或强制转换。 :)
  • 谢谢 - 我认为你很接近,但它说'操作数类型冲突:int 与时间不兼容'
  • 架构如下:CREATE TABLE [dbo].[MyTable]( [UserId] [int] NOT NULL, [Event] [varchar](30) NOT NULL, [EventTimestamp] [datetime] NOT NULL ) ON [PRIMARY]
  • 您可以在this link参考答案
猜你喜欢
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 2022-08-18
  • 2010-10-28
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多