问题
I need a query to pair interleaved data of 'start' and 'end' times into one neat output, but my main hurdle is with how the data is stored in an interleaved format within the ProcessTimer table.
Input table 1
I have a table called ProcessTimer with three columns.
- ProcessTimerId INT (PRIMARY KEY)
- ProcessTimerDatetime DATETIME
- ProcessTimerAction VARCHAR(5)
- ProcessId INT (FOREIGN KEY)
'ProcessTimerAction' is only ever set to the value 'START' or 'STOP', which ties in to the 'ProcessTimerDatetime' column, because 'ProcessTimerDatetime' stores a DATETIME value of when a Process has started or stopped.
Each Process is identified via a ProcessId, and that links to another table called Process, which has some details about each Process.
Input table 2
The Process table is set up as follows:
- ProcessId INT (PRIMARY KEY)
- ProcessName VARCHAR(255)
- ProcessOwner VARCHAR(255)
Logically, a Process's START action should always be followed by a STOP action, and display in pairs, however errors in the data mean that there isn't always a STOP action for every START action. In these instances there's nothing I can do but display a NULL for the missing STOP entry
Desired output
I wish to represent the data in grid with the following headings.
- ProcessOwner
- ProcessName
- ProcessStartTime
- ProcessEndTime
Has anyone achieved something like this before?
I'm unsure how to begin to tackle creating the query I need.
Example data
ProcessTimer table
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
Process table
ProcessId,ProcessName,ProcessOwner
445,CTC hourlies,Sarah Parkes
636,Garage import,John Dean
883,DF task,Kate Duke
回答1:
Here's one implementation:
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'
Output for above data:
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
来源:https://stackoverflow.com/questions/42364642/query-to-pair-interleaved-start-and-end-times