【问题标题】:Query to pair interleaved start and end times查询以配对交错的开始和结束时间
【发布时间】:2017-02-21 10:22:32
【问题描述】:

我需要一个查询来将“开始”和“结束”时间的交错数据配对到一个整洁的输出中,但我的主要障碍是数据如何以交错格式存储在 ProcessTimer表。

输入表1

我有一个名为 ProcessTimer 的表,其中包含三列。

  • ProcessTimerId INT(主键)
  • ProcessTimerDatetime DATETIME
  • ProcessTimerAction VARCHAR(5)
  • ProcessId INT(外键)

'ProcessTimerAction' 仅设置为值 'START' 或 'STOP',这与 'ProcessTimerDatetime' 列相关,因为 ' ProcessTimerDatetime' 存储进程启动或停止时间的 DATETIME 值。

每个进程通过 ProcessId 标识,并链接到另一个名为 Process 的表,其中包含有关每个进程的一些详细信息。

输入表2

Process表设置如下:

  • ProcessId INT(主键)
  • 进程名称 VARCHAR(255)
  • ProcessOwner VARCHAR(255)

从逻辑上讲,进程的 START 动作应该始终跟在 STOP 动作之后,并成对显示,但是数据中的错误意味着每个 START 动作并不总是有一个 STOP 动作。在这些情况下,我无能为力,只能为丢失的 STOP 条目显示 NULL

期望的输出

我希望用以下标题在网格中表示数据。

  • ProcessOwner
  • 进程名称
  • ProcessStartTime
  • ProcessEndTime

以前有人做过类似的事情吗?

我不确定如何着手创建我需要的查询。

示例数据

ProcessTimer

ProcessTimerId,ProcessTimerDatetime,ProcessTimerAction,ProcessId
1,1/1/2017 08:00:34,START,883
2,1/1/2017 08:03:76,STOP,883
3,1/1/2017 08:03:77,START,445
4,1/1/2017 08:03:79,START,636
5,1/1/2017 08:05:77,STOP,445
6,1/1/2017 08:07:34,START,445
7,1/1/2017 08:09:23,START,445
8,1/1/2017 08:12:61,STOP,636
9,1/1/2017 08:14:65,STOP,445

流程

ProcessId,ProcessName,ProcessOwner
445,CTC hourlies,Sarah Parkes
636,Garage import,John Dean
883,DF task,Kate Duke

【问题讨论】:

  • 您是说将开始和停止时间放在一行吗?
  • 如果是在由 ProcessId 分区的 Row_Number 处。使用 RID = RID + 1 AND ProcessId = ProcessId 加入它自己

标签: sql sql-server datetime report


【解决方案1】:

这是一个实现:

WITH ProcessTimerWithRowNum([ProcessId], [ProcessTimerAction], [ProcessTimerDatetime],[rno])
AS
( SELECT [ProcessId],
         [ProcessTimerAction],
         [ProcessTimerDatetime], 
         ROW_NUMBER() OVER(PARTITION BY ProcessId ORDER BY ProcessTimerId) AS [rno] 
  FROM  ProcessTime )

SELECT PT.[ProcessId], 
       P.[ProcessOwner], 
       P.[ProcessName], 
       PT.[ProcessTimerDatetime] AS StartTime, 
       DPT.ProcessTimerDatetime AS EndTime FROM

ProcessTimerWithRowNum PT 

LEFT JOIN

ProcessTimerWithRowNum DPT

ON PT.ProcessId = DPT.ProcessId  AND DPT.ProcessTimerAction = 'STOP' AND DPT.rno = PT.rno + 1

INNER JOIN Process P ON PT.ProcessId = P.ProcessId

WHERE PT.ProcessTimerAction = 'START'

以上数据的输出:

ProcessOwner | ProcessName | StartTime | EndTime  

445 |Sarah Parkes|  CTC hourlies|   1/1/2017 08:03:77|  1/1/2017 08:05:77

445 |Sarah Parkes|  CTC hourlies|   1/1/2017 08:07:34|  NULL

445 |Sarah Parkes|  CTC hourlies|   1/1/2017 08:09:23|  1/1/2017 08:14:65

636 |John Dean| Garage import|  1/1/2017 08:03:79|  1/1/2017 08:12:61

883 |Kate Duke| DF task|    1/1/2017 08:00:34|  1/1/2017 08:03:76

【讨论】:

  • 我必须做的唯一更改是 OVER(PARTITION BY ProcessId ORDER BY ProcessTimerId) AS [rno] OVER(PARTITION BY ProcessId ORDER BY ProcessTimerDateTime) AS [rno] 。我认为这是因为有时时间可以不按顺序进入数据库。这听起来对你吗?我目前有我的 L 牌,可以理解这个查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多