SQL Server查询 - 事件之间事件时间的总和

时间:2017-09-26 08:26:43

标签: sql sql-server

我需要得到“生产”的总和。失败之间的事件'事件。这有点难以解释,所以让我们看看数据以及所需的结果。见下表。输入表也以底部的文本形式给出。

黄色项目是失败事件(代码100)。绿色项目是生产事件(代码200)。我需要在失败事件之间生成时间,如上表所示。请注意,上一个失败事件之后没有任何生产事件,因此需要忽略它。

我的猜测是Rank()函数会涉及某个地方,但我正在努力解决这个问题!

Event data

Result data

+---------------------+---------------------+-----------------+------------+-----------+
| StartDate           | EndDate             | DurationInHours | Equipment  | EventCode |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-01 06:31:51 | 2014-01-01 09:14:57 | 2.7183          | Equipment1 | 100       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-01 09:17:20 | 2014-01-01 13:34:40 | 4.2889          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-01 21:59:49 | 2014-01-01 23:20:29 | 1.3444          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-03 22:23:33 | 2014-01-03 22:41:57 | 0.3067          | Equipment1 | 100       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-03 22:51:49 | 2014-01-04 05:48:43 | 6.9483          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 06:26:18 | 2014-01-04 14:04:20 | 7.6339          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 14:32:44 | 2014-01-04 18:07:29 | 3.5792          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 18:27:16 | 2014-01-04 22:40:37 | 4.2225          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 22:40:37 | 2014-01-04 23:13:15 | 0.5439          | Equipment1 | 100       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 23:13:15 | 2014-01-04 23:13:20 | 0.0014          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-04 23:13:26 | 2014-01-05 07:24:11 | 8.1792          | Equipment1 | 200       |
+---------------------+---------------------+-----------------+------------+-----------+
| 2014-01-05 07:24:11 | 2014-01-05 09:24:45 | 2.0094          | Equipment1 | 100       |
+---------------------+---------------------+-----------------+------------+-----------+

3 个答案:

答案 0 :(得分:2)

这是另一种我认为会更有效的方法。不使用带有TOP(1)和ORDER BY的APPLY,这种方法使用LEAD()OVER()然后在这些日期边界内聚合。

请参阅此备选方案SQL Fiddle

查询1

select 
      t1.Equipment
    , grp.StartDate
    , grp.EndDate
    , sum(t1.DurationInHours) sumDurationInHours
from table1 as t1
inner join (
    select
          t2.Equipment
        , t2.StartDate
        , lead(t2.EndDate) over(partition by t2.Equipment order by t2.EndDate) EndDate
    from table1 as t2
    where t2.eventcode = 100
   ) grp on t1.Equipment = grp.Equipment
        and t1.StartDate between grp.StartDate and grp.EndDate
where t1.eventcode = 200
group by
      t1.Equipment
    , grp.StartDate
    , grp.EndDate

<强> Results

|  Equipment |            StartDate |              EndDate | sumDurationInHours |
|------------|----------------------|----------------------|--------------------|
| Equipment1 | 2014-01-01T06:31:51Z | 2014-01-03T22:41:57Z |             5.6333 |
| Equipment1 | 2014-01-03T22:23:33Z | 2014-01-04T23:13:15Z |            22.3853 |
| Equipment1 | 2014-01-04T22:40:37Z | 2014-01-05T09:24:45Z |             8.1806 |

答案 1 :(得分:1)

我测试了这个 我希望它符合你的要求。

Create table test(STARTDATE datetime, enddate datetime, eventcode int)

insert into test 
Select '2017-01-01 06:31:51',  '2017-01-01 09:14:51'  ,100 union all
Select '2017-01-01 10:31:51',  '2017-01-01 11:14:51'  ,200 union all
Select '2017-01-01 12:31:51',  '2017-01-01 15:15:51'  ,200 union all
Select '2017-01-01 17:21:51',  '2017-01-01 18:14:51'  ,100 union all
Select '2017-01-01 19:31:51',  '2017-01-01 19:51:51'  ,200 union all
Select '2017-01-01 20:11:51',  '2017-01-01 21:14:51'  ,100 union all
Select '2017-01-01 22:31:51',  '2017-01-01 23:14:51'  ,200 

with cte as
(
Select ROW_NUMBER() over( order by startdate) rn, * From test Where  
eventcode = 100 
)
Select a.STARTDATE as failuredate,
cast(datediff(mi,a.STARTDATE, b.STARTDATE)as varchar(10))  DiffInMinutes
from cte a
left join cte b    on a.rn+1 = b.rn

只需将DiffInMinutes转换为hh:mm。

答案 2 :(得分:1)

您可以使用APPLY(多次),其中一个apply的别名可以在下一个中使用。请注意,此方法可能不适合大型表格。

SQL Fiddle

看到它在这里工作

MS SQL Server 2014架构设置

CREATE TABLE Table1
    ([StartDate] datetime, [EndDate] datetime, [DurationInHours] decimal(12,4), [Equipment] varchar(10), [EventCode] int)
;

INSERT INTO Table1
    ([StartDate], [EndDate], [DurationInHours], [Equipment], [EventCode])
VALUES
    ('2014-01-01 06:31:51', '2014-01-01 09:14:57', 2.7183, 'Equipment1', 100),
    ('2014-01-01 09:17:20', '2014-01-01 13:34:40', 4.2889, 'Equipment1', 200),
    ('2014-01-01 21:59:49', '2014-01-01 23:20:29', 1.3444, 'Equipment1', 200),
    ('2014-01-03 22:23:33', '2014-01-03 22:41:57', 0.3067, 'Equipment1', 100),
    ('2014-01-03 22:51:49', '2014-01-04 05:48:43', 6.9483, 'Equipment1', 200),
    ('2014-01-04 06:26:18', '2014-01-04 14:04:20', 7.6339, 'Equipment1', 200),
    ('2014-01-04 14:32:44', '2014-01-04 18:07:29', 3.5792, 'Equipment1', 200),
    ('2014-01-04 18:27:16', '2014-01-04 22:40:37', 4.2225, 'Equipment1', 200),
    ('2014-01-04 22:40:37', '2014-01-04 23:13:15', 0.5439, 'Equipment1', 100),
    ('2014-01-04 23:13:15', '2014-01-04 23:13:20', 0.0014, 'Equipment1', 200),
    ('2014-01-04 23:13:26', '2014-01-05 07:24:11', 8.1792, 'Equipment1', 200),
    ('2014-01-05 07:24:11', '2014-01-05 09:24:45', 2.0094, 'Equipment1', 100)
;

查询1

select
t1.startdate, ca1.nextend, ca2.sumDurationInHours
from table1 as t1
cross apply (
  select top(1) EndDate as nextend
  from table1 as t2
  where t2.StartDate > t1.StartDate and t2.EventCode = 100
  order by t2.StartDate 
  ) ca1
cross apply (
  select sum(DurationInHours) as sumDurationInHours
  from table1 as t3
  where t3.StartDate >= t1.StartDate 
  and t3.EndDate < ca1.nextend
  and t3.EventCode = 200
  ) ca2
where t1.eventcode = 100

<强> Results

|            startdate |              nextend | sumDurationInHours |
|----------------------|----------------------|--------------------|
| 2014-01-01T06:31:51Z | 2014-01-03T22:41:57Z |             5.6333 |
| 2014-01-03T22:23:33Z | 2014-01-04T23:13:15Z |            22.3839 |
| 2014-01-04T22:40:37Z | 2014-01-05T09:24:45Z |             8.1806 |