1

我有一个包含n 个历史条目的表,记录了活动/非活动的变化。

[Id]   [ParentId] [Date]                   [Status]
<guid> 0          2013-05-03 15:51:24.810  'Active'
<guid> 0          2013-05-03 15:52:10.773  'Inactive'
<guid> 0          2013-05-03 15:54:26.710  'Active'
<guid> 0          2013-05-03 17:09:27.327  'Inactive'

我正在尝试确定该项目在其整个历史记录中处于“活动”状态的时间。用游标迭代历史并使用DATEDIFF它来计算它的性能很差。我试图避免使用 SQLCLR,但可能会以相当便宜的方式在内存中做到这一点......有谁知道一个好的 SQL-native、高性能的方法来完成这个?

4

1 回答 1

2

关键思想是在给定的活动记录之后获取下一个非活动记录。

如果您使用的是 SQL Server 2012,则可以使用该lead()功能。否则,我认为相关子查询是表示需要做什么的最简单方法。(您也可以使用显式执行此操作join,我只是认为这更清楚)。

select guid, sum(datediff(ms, t.[date], t.nextInactive)) as duration_ms
from (select t.*,
             (select min([date])
              from t t2
              where t2.guid = t.guid and t2.[date] > t.[date] and t2.status = 'Inactive'
             ) as nextInactive
      from t
      where t.status = 'Active'
     ) t
group by guid

一旦你有了下一个不活动的记录,然后只取差值(在这种情况下以毫秒为单位)并将值相加。

如果最后一条记录是活动记录,那么它将被忽略。如果你想计算,那么你需要coalesce(t.nextInactive, <some value here>)在外部查询中使用。

如果您在guid, status, date.

于 2013-05-07T19:51:55.683 回答