T-SQL脚本用于计算多行之间的时差

时间:2014-07-01 20:31:39

标签: sql-server database tsql

我有一个看起来像这样的表:

EventDateTime           EventName   AppID
-----------------------------------------
2014-06-27 22:17:19     GotFocus    1000
2014-06-27 22:17:20     LostFocus   1000
2014-06-27 22:17:22     GotFocus    1005
2014-06-27 22:17:24     LostFocus   1005
2014-06-27 22:17:27     GotFocus    1000
2014-06-27 22:17:30     LostFocus   1000
2014-06-27 22:17:37     GotFocus    1005
2014-06-27 22:17:40     LostFocus   1005

我需要做的是创建一个T-SQL脚本,计算每个应用程序处于焦点的持续时间(即每个应用程序的所有LostFocus-GotFocus的总和)。所以对于上面的表我应该得到:

Duration    AppID
------------------
4           1000
5           1005

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:1)

正如xQbert指出的那样,取决于你的数据是多么干净。假设每个GotFocus都有一个LostFocus,并且LostFocus EventDateTime大于或等于GotFocus EventDateTime,这应该可以工作(小提琴:http://sqlfiddle.com/#!3/f36a4/14):

WITH cteGotFocus
AS
(
  SELECT  AppID,
          ROW_NUMBER() OVER(PARTITION BY AppID ORDER BY EventDateTime) AS RID,
          EventDateTime
  FROM    Table1
  WHERE   EventName = 'GotFocus'
),
cteLostFocus
AS
(
  SELECT  AppID,
          ROW_NUMBER() OVER(PARTITION BY AppID ORDER BY EventDateTime) AS RID,
          EventDateTime
  FROM    Table1
  WHERE   EventName = 'LostFocus'
)

SELECT   SUM(DATEDIFF(s, gf.EventDateTime, lf.EventDateTime)) AS Duration,
         gf.AppID
FROM     cteGotFocus gf INNER JOIN cteLostFocus lf
         ON gf.AppID = lf.AppID AND
            gf.RID = lf.RID
GROUP BY  gf.AppID
ORDER BY  gf.AppID;

编辑:只是缩减了一些不必要的CTE。小提琴链接已更新。

答案 1 :(得分:0)

我喜欢VBlades的回答(我认为它更容易阅读),但这可能会有所改善:

select g.AppId, sum(DATEDIFF(S, g.EventDateTime, l.EventDateTime)) Duration
from Event g
join Event l on g.AppId = l.AppId and g.EventName = 'GotFocus' and l.EventName = 'LostFocus'
where l.EventDateTime = (select MIN(eventDateTime) from Event e3 where e3.AppId = g.AppId and e3.EventName = 'LostFocus' and e3.EventDateTime > g.EventDateTime)
group by g.AppId
order by g.AppId

SQL Fiddle

答案 2 :(得分:0)

如果事件序列始终是GF,那么您可以使用此查询:

select y.appid, y.groupnum, datediff(second, y.gotfocus, y.lostfocus) seconds
from (( row_number() over(partition by appid order by eventdatetime) + 1) / 2 as groupnum,
appid, eventname, eventdatetime
from dbo.mytable) x
pivot( max(x.eventdatetime) for x.eventname in ([gotfocus], [lostfocus]) y

注意:我没有测试过这个解决方案。

答案 3 :(得分:-1)

我采用相同的方案,但有不同的数据类型,答案很容易阅读

select kk.bb - jj.aa from
(
    select a , eventname ,sum(c) as aa
    from #tem1
    where eventname = 'login'
    group by a,eventname
) as jj

join 
(
    select a , eventname ,sum(c) as bb
    from #tem1
    where eventname = 'logoff'
    group by a,eventname
) as kk
on jj.a = kk.a