如何使用T-SQL计算表中事件记录之间的时间

时间:2018-04-03 17:26:01

标签: sql sql-server-2012

我简化了一个我被要求解决的问题。下面我有一张类似的表。

id:          primary_key
person:      varchar(20)
logdatetime: datetime
description: varchar(30)

使用此表,它以下列方式存储数据。

id     person   logdatetime         description
-----------------------------------------------
4503   Joe      4/3/2018 11:00:00   Lunch
4504   Sam      4/3/2018 11:15:00   Lunch
4512   Joe      4/3/2018 12:05:00   Physics
4514   Sam      4/3/2018 12:05:00   Physics
4518   Sam      4/3/2018 13:05:00   Library
4521   Joe      4/3/2018 13:10:00   Language Arts
4522   Joe      4/3/2018 14:15:00   Day Complete
4526   Sam      4/3/2018 16:08:00   Day Complete

对于每个人,是否可以使用SQL来计算每个类/活动所花费的时间。在过去,我使用临时表将这些事件链接在一起,但这是一个实时系统,数据不断增长。理想的结果将如下所示。通过这样的数据结构,我可以轻松计算事件持续的总时间。

id     person   logdatetime         enddatetime         description
-------------------------------------------------------------------
4503   Joe      4/3/2018 11:00:00   4/3/2018/12:05:00   Lunch
4504   Sam      4/3/2018 11:15:00   4/3/2018 12:05:00   Lunch
4512   Joe      4/3/2018 12:05:00   4/3/2018 13:10:00   Physics
4514   Sam      4/3/2018 12:05:00   4/3/2018 13:05:00   Physics
4518   Sam      4/3/2018 13:05:00   4/3/2018 16:08:00   Library
4521   Joe      4/3/2018 13:10:00   4/3/2018 14:15:00   Language Arts
4522   Joe      4/3/2018 14:15:00   null                Day Complete
4526   Sam      4/3/2018 16:08:00   null                Day Complete

构建报告的好SQL选项是什么,它总结了在类/活动中花费的时间?我没有选择更改数据在此表中的存储方式。这适用于SQL Server数据库。

4 个答案:

答案 0 :(得分:2)

让我们试试Joe

--just to get some sample data
if object_id('tempdb..#x') is not null drop table #x
CREATE TABLE #x(id INT, person VARCHAR(5), logdatetime DATETIME, description VARCHAR(20))
INSERT INTO #x(id,person,logdatetime,description) VALUES
(4503,   'Joe',      '4/3/2018 11:00:00',   'Lunch'),
(4504,   'Sam',      '4/3/2018 11:15:00',   'Lunch'),
(4512,   'Joe',      '4/3/2018 12:05:00',   'Physics'),
(4514,   'Sam',      '4/3/2018 12:05:00',   'Physics'),
(4518,   'Sam',      '4/3/2018 13:05:00',   'Library'),
(4521,   'Joe',      '4/3/2018 13:10:00',   'Language Arts'),
(4522,   'Joe',      '4/3/2018 14:15:00',   'Day Complete'),
(4526,   'Sam',      '4/3/2018 16:08:00',   'Day Complete')

--actual query
SELECT
      description,
      a.logdatetime AS 'Start',
      (SELECT TOP 1 b.logdatetime FROM #x AS b WHERE b.person=a.person AND b.id>a.id ORDER BY b.id) AS 'End',
      DATEDIFF(minute,a.logdatetime,
      (SELECT TOP 1 b.logdatetime FROM #x AS b WHERE b.person=a.person AND b.id>a.id ORDER BY b.id) ) AS 'TimeDiff(Min)'
FROM #x AS a
WHERE a.person='Joe'

输出

description   Start                      End                   TimeDiff(Min)
Lunch         2018-04-03 11:00:00.000   2018-04-03 12:05:00.000   65
Physics       2018-04-03 12:05:00.000   2018-04-03 13:10:00.000   65
Language Arts 2018-04-03 13:10:00.000   2018-04-03 14:15:00.000   65
Day Complete  2018-04-03 14:15:00.000   NULL                      NULL

答案 1 :(得分:2)

这是使用LEAD()的版本(如果你有2012 +)

if object_id('tempdb.dbo.#x') is not null drop table #x
create table #x
(
    Id int, 
    Person varchar(5), 
    LogDateTime datetime, 
    Description varchar(20)
)
insert into #x
(
    id,
    person,
    logdatetime,
    description
) 
values
    (4503,   'Joe',      '4/3/2018 11:00:00',   'Lunch'),
    (4504,   'Sam',      '4/3/2018 11:15:00',   'Lunch'),
    (4512,   'Joe',      '4/3/2018 12:05:00',   'Physics'),
    (4514,   'Sam',      '4/3/2018 12:05:00',   'Physics'),
    (4518,   'Sam',      '4/3/2018 13:05:00',   'Library'),
    (4521,   'Joe',      '4/3/2018 13:10:00',   'Language Arts'),
    (4522,   'Joe',      '4/3/2018 14:15:00',   'Day Complete'),
    (4526,   'Sam',      '4/3/2018 16:08:00',   'Day Complete')

select 
    Id,
    Person,
    LogDateTime,
    EndDateTime = lead(LogDateTime, 1, null) over (partition by Person order by (Id)),
    Description
from #x
order by id

答案 2 :(得分:1)

SELECT id, person, logdatetime, 
    LEAD(logdatetime, 1,null) OVER (PARTITION BY person ORDER BY id) AS  enddatetime, description
FROM test
ORDER BY id

答案 3 :(得分:0)

尝试使用铅

在几分钟内获得时间
SELECT Person, description, logdatetime, 
CASE WHEN TimeSpent < 0 THEN 0 ELSE TimeSpent END AS TimeSpent
 FROM (SELECT Person, description, logdatetime,
 (DATEDIFF(MINUTE,logdatetime,LEAD(logdatetime,1,0) OVER (PARTITION BY person ORDER BY id))) AS TimeSpent  FROM Tempx) AS SEL