计算阶段之间的持续时间



我有以下历史表(记录用户操作):

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
| parent_id | property_names                                                          | changed_property                                                                                                                                                                                                                                                                                | time_c        | outcome |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 123456    | {PhaseId,LastUpdateTime}                                                | {"PhaseId":{"newValue":"Fulfill","oldValue":"Approve"},"LastUpdateTime":{"newValue":1671027321749,"oldValue":1671027321170}}                                                                                                                                                                    | 1671027321749 | success |
| 123456    | {PhaseId,LastUpdateTime,ApprovalStatus}                                 | {"PhaseId":{"newValue":"Approve","oldValue":"Log"},"LastUpdateTime":{"newValue":1671011168777,"oldValue":1671011168043},"ApprovalStatus":{"newValue":"InProgress"}}                                                                                                                             | 1671011168777 | success |
| 123456    | {LastUpdateTime,PhaseId,Urgency}                                        | {"LastUpdateTime":{"newValue":1671011166077},"PhaseId":{"newValue":"Log"},"Urgency":{"newValue":"TotalLossOfService"}}                                                                                                                                                                          | 1671011166077 | success |
| 123456    | {LastUpdateTime,ApprovalStatus}                                         | {"LastUpdateTime":{"newValue":1671027321170,"oldValue":1671027320641},"ApprovalStatus":{"newValue":"Approved","oldValue":"InProgress"}}                                                                                                                                                         | 1671027321170 | success |
| 123456    | {PhaseId,LastUpdateTime,ExecutionEnd_c}                                 | {"PhaseId":{"newValue":"Accept","oldValue":"Fulfill"},"LastUpdateTime":{"newValue":1671099802675,"oldValue":1671099801501},"ExecutionEnd_c":{"newValue":1671099802374}}                                                                                                                         | 1671099802675 | success |
| 123456    | {PhaseId,LastUpdateTime,CompletionCode}                                 | {"PhaseId":{"newValue":"Review","oldValue":"Accept"},"LastUpdateTime":{"newValue":1671099984979,"oldValue":1671099982723},"CompletionCode":{"oldValue":"CompletionCodeAbandonedByUser"}}                                                                                                        | 1671099984979 | success |
| 123456    | {PhaseId,LastUpdateTime,ExecutionStart_c}                               | {"PhaseId":{"newValue":"Fulfill","oldValue":"Review"},"LastUpdateTime":{"newValue":1671100012012,"oldValue":1671099984979},"ExecutionStart_c":{"newValue":1671100011728,"oldValue":1671027321541}}                                                                                              | 1671100012012 | success |
| 123456    | {UserAction,PhaseId,LastUpdateTime,ExecutionEnd_c}                      | {"UserAction":{"oldValue":"UserActionReject"},"PhaseId":{"newValue":"Accept","oldValue":"Fulfill"},"LastUpdateTime":{"newValue":1671100537178,"oldValue":1671100535959},"ExecutionEnd_c":{"newValue":1671100536730,"oldValue":1671099802374}}                                                   | 1671100537178 | success |
| 123456    | {PhaseId,Active,CloseTime,LastUpdateTime,LastActiveTime,ClosedByPerson} | {"PhaseId":{"newValue":"Close","oldValue":"Accept"},"Active":{"newValue":false,"oldValue":true},"CloseTime":{"newValue":1671101084529},"LastUpdateTime":{"newValue":1671101084788,"oldValue":1671101083903},"LastActiveTime":{"newValue":1671101084529},"ClosedByPerson":{"newValue":"511286"}} | 1671101084788 | success |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------        


列描述:

parent_id:指向父元素的链接

property_names:有修改的属性

changed_property:属性的新值。例:

{
"PhaseId":{
"newValue":"Fulfill",
"oldValue":"Approve"
},
"LastUpdateTime":{
"newValue":1671027321749,
"oldValue":1671027321170
}
}

属性PhaseId将值从Approve更改为Fulfill

time_c: Unix更新时间戳

:更新状态

我的目标是计算每个阶段的持续时间。期望输出:

------------------------------------------------------------
| parent_id | Log  | Approve  | Fulfill  | Accept | Review |
------------------------------------------------------------
| 123456    | 2700 | 16152972 | 73006092 | 729914 | 27033  | 
------------------------------------------------------------

Log:1671011168777 - 1671011166077 = 2700

批准:1671027321749 - 1671011168777 = 16152972

完成:(1671100537178 - 1671100012012) + (1671099802675 - 1671027321749) = 73006092

接收:(1671101084788 - 1671100537178) + (1671099984979 - 1671099802675) = 729914

Review:1671100012012 - 1671099984979 = 27033

此时,我能够检索PhaseId的新旧值,并将unix时间戳转换为datetime。我的问题是如何使用SQL 计算阶段的持续时间我当前的SQL请求:

SELECT * FROM
(SELECT 
parent_id,
property_names,
changed_property,
time_c,
to_char(to_timestamp(time_c/1000.0) at time zone 'Europe/Paris', 'yyyy-mm-dd hh24:mi:ss') AS "time to datetime",
outcome,
changed_property::json->'PhaseId'->> 'newValue' AS "PhaseId (new)",
changed_property::json->'PhaseId'->> 'oldValue' AS "PhaseId (old)"
FROM history 
WHERE array_to_string(property_names, ', ') like '%PhaseId%'
ORDER BY time_c DESC) AS temp_c
/*
WHERE "PhaseId (new)" = 'Close'
OR "PhaseId (old)" = 'Close'
*/

结果(不相关数据隐藏):

-----------------------------------------------------------------------------------
| parent_id | time_c        | time to datetime    | PhaseId (new) | PhaseId (old) |
-----------------------------------------------------------------------------------
| 123456    | 1671101084788 | 2022-12-15 11:44:44 | Close         | Accept        |
| 123456    | 1671100537178 | 2022-12-15 11:35:37 | Accept        | Fulfill       |
| 123456    | 1671100012012 | 2022-12-15 11:26:52 | Fulfill       | Review        |
| 123456    | 1671099984979 | 2022-12-15 11:26:24 | Review        | Accept        |
| 123456    | 1671099802675 | 2022-12-15 11:23:22 | Accept        | Fulfill       |
| 123456    | 1671027321749 | 2022-12-14 15:15:21 | Fulfill       | Approve       |
| 123456    | 1671011168777 | 2022-12-14 10:46:08 | Approve       | Log           |
| 123456    | 1671011166077 | 2022-12-14 10:46:06 | Log           | null          |
-----------------------------------------------------------------------------------

数据库文件:https://www.db-fiddle.com/f/ckqtYy3EuASF4RdF9dSEcv/2

select * from crosstab(
'
with ordered_changes as (select parent_id,
time_c,
changed_property::json -> ''PhaseId'' ->> ''newValue'' AS PhaseId_New,
changed_property::json -> ''PhaseId'' ->> ''oldValue'' AS PhaseId_Old,
property_names,
changed_property,
outcome
from history
where arraycontains(property_names, ARRAY [''PhaseId''])
order by parent_id, time_c desc),
all_stage_durations as (select oc.parent_id,
oc.time_c - lag(oc.time_c, 1) over (order by time_c) as duration,
oc.PhaseId_old,
oc.time_c                                               end_ts,
lag(oc.PhaseId_New, 1) over (order by time_c),
lag(oc.time_c, 1) over (order by time_c)                start_ts
from ordered_changes oc)
select asd.parent_id, asd.PhaseId_old stage, sum(asd.duration) total_time
from all_stage_durations asd
where asd.PhaseId_old is not null
group by asd.parent_id, asd.PhaseId_old
order by parent_id, stage
',
'select stage from (' ||
'select distinct changed_property::json -> ''PhaseId'' ->> ''newValue'' AS stage from history union ' ||
'select distinct changed_property::json -> ''PhaseId'' ->> ''oldValue'' AS stage from history ) a ' ||
'where stage is not null order by stage'
)
as ct(parent_id int, Accept int, Approve int, Close int, Fulfill int, Log int, Review int)
;

我是这样计算的:

WITH temp AS (
SELECT  parent_id,
changed_property::json->'PhaseId'->> 'newValue' AS phase,
time_c,
LEAD(time_c,1) OVER (
PARTITION BY parent_id
ORDER BY parent_id,time_c
) next_time
FROM history
where 'PhaseId' = ANY(property_names) 
)   
SELECT  parent_id,
phase,
justify_interval(make_interval(secs =>SUM((next_time-time_c)/1000))) AS "Durations"
FROM temp
GROUP BY parent_id,phase
ORDER BY parent_id

我使用了函数LEAD

小提琴:https://www.db-fiddle.com/f/ckqtYy3EuASF4RdF9dSEcv/4

最新更新