如何计算工作日的间隔和整个间隔

问题描述 投票:0回答:1

我有以下数据:

entity_id 阶段 old_phase 时间 下一次
1 '日志' 1654781946989 1654781949732
1 '批准' '日志' 1654781949732 1654781952676
1 '满足' '批准' 1654781952676 1677506971778
1 '接受' '满足' 1677506971778 1677518742552
1 '回顾' '接受' 1677518742552 1678097845979
1 '满足' '回顾' 1678097845979 1678097847325
1 '接受' '满足' 1678097847325 1678097977816
1 '回顾' '接受' 1678097977816
2 '日志' 1645088036633 1645088043676
2 '批准' '日志' 1645088043676 1645088047318
2 '满足' '批准' 1645088047318 1677500808099
2 '关闭' '满足' 1677500808099

time
next_time
表示为以毫秒为单位的 unix 时间戳。

目标是计算每个

entity_id
阶段的每个
Fulfill
的持续时间总和。

我的数据库是只读的,所以我不能创建函数。

预期结果应该是这样的:

entity_id 时长(不包括周六和周日) 持续时间满
1 186天22小时30分21秒 {“月”:8,“天”:22,“小时”:22,“分钟”:30,“秒”:21}
2 267天3小时32分41秒 {“年”:1,“天”:15,“小时”:3,“分钟”:32,“秒”:41}

电流输出:

entity_id 时长(不包括周六和周日) 持续时间满
1 186天22小时30分19秒 {“月”:8,“天”:22,“小时”:22,“分钟”:30,“秒”:19}
1 -76天0小时0分2秒 {“秒”:2}
2 267天3小时32分41秒 {“年”:1,“天”:15,“小时”:3,“分钟”:32,“秒”:41}

如果

2 Fulfill
上有
1 entity_id
相,则输出不正确。

我的 SQL 请求:

WITH temp2 AS (
    SELECT
        entity_id,
        old_phase,
        phase,
        time,
        next_time,
        to_timestamp(to_char(to_timestamp("time"/1000.0) at time zone 'Europe/Paris', 'yyyy-mm-dd HH24:MI:SS'), 'yyyy-mm-dd HH24:MI:SS') at time zone 'Europe/Paris' AS "TIME 2",
        to_timestamp(to_char(to_timestamp("next_time"/1000.0) at time zone 'Europe/Paris', 'yyyy-mm-dd HH24:MI:SS'), 'yyyy-mm-dd HH24:MI:SS') at time zone 'Europe/Paris'AS "NEXT TIME 2",
        ((next_time - time)/1000.0) AS DIFF
    FROM 
        tbl_history
    WHERE phase = 'Fulfill'
),parms (entity_id, start_date, end_date) AS
(
    SELECT 
        entity_id,
        "TIME 2"::timestamp,
        "NEXT TIME 2"::timestamp
    FROM 
        temp2
), weekend_days (entity_id, wkend) AS 
(
    SELECT 
        entity_id,
        SUM(case when extract(isodow from d) in (6, 7) then 1 else 0 end) 
    FROM 
        parms
    CROSS JOIN 
        generate_series(start_date, end_date, interval '1 day') dn(d)
    GROUP BY entity_id
)

SELECT 
    entity_id,
    CONCAT(
        extract(day from diff), ' days ', 
        extract( hours from diff)   , ' hours ', 
        extract( minutes from diff) , ' minutes ', 
        extract( seconds from diff)::int , ' seconds '
    ) AS "Duration (excluding saturday and sunday)",
    justify_interval(end_date::timestamp - start_date::timestamp) AS "Duration full"
FROM (
    SELECT 
        start_date,
        end_date,
        entity_id,
        (end_date-start_date) - (wkend * interval '1 day') AS diff
    FROM parms 
    JOIN weekend_days USING(entity_id)
) sq;

演示:https://www.db-fiddle.com/f/ujJe2t9CYLhoRm23RAbSbv/2

如何计算每个 entity_id 的 Fulfill 阶段的完整持续时间(有和没有工作日)?

sql postgresql
1个回答
0
投票

可以求出每个

sum
的时间间隔(包括
justify_interval
)的
entity_id
s,求出
entity_id
所有间隔之间的周末总数,然后join结果,减去周末数从总和区间:

with cte as (
   select t.*, to_timestamp(to_char(to_timestamp(t.time/1000.0) at time zone 'Europe/Paris', 'yyyy-mm-dd HH24:MI:SS'), 'yyyy-mm-dd HH24:MI:SS') at time zone 'Europe/Paris' s,
    to_timestamp(to_char(to_timestamp(t.next_time/1000.0) at time zone 'Europe/Paris', 'yyyy-mm-dd HH24:MI:SS'), 'yyyy-mm-dd HH24:MI:SS') at time zone 'Europe/Paris' e
   from tbl_history t
),
dt_diff as (
   select t.entity_id, t.phase, sum(t.e - t.s) dr, sum(justify_interval(t.e - t.s)) dt 
   from cte t where t.phase = 'Fulfill' group by t.entity_id, t.phase
),
weekends as (
  select t.entity_id, t.phase, sum(case when extract(dow from v) in (0, 6) then 1 else 0 end) wt 
  from cte t cross join generate_series(t.s, t.e, interval '1 day') v  
  where t.phase = 'Fulfill' group by t.entity_id, t.phase
)
select t1.entity_id, t1.dr - make_interval(days => w.wt::int) "Duration (excluding saturday and sunday)", 
   (select jsonb_object_agg(d.key, d.value) from jsonb_each(
      jsonb_build_object('years', extract(years from t1.dt), 
       'months', extract(months from t1.dt), 
       'days', extract(days from t1.dt), 
       'hours', extract(hours from t1.dt), 
       'minutes', extract(minutes from t1.dt), 
       'seconds', extract(seconds from t1.dt))) d where d.value::int > 0) "Duration full"
from dt_diff t1 join weekends w on w.entity_id = t1.entity_id 

见小提琴

© www.soinside.com 2019 - 2024. All rights reserved.