繁体   English   中英

SQL:计算历史表上日期范围之间的天数

[英]SQL : calculate the number of days between date range on a history table

我有一个Person表,其中有一个Status列,反映了该人任务的当前状态。

PersonId    Status
--------------------------------------------
1           In Progress
2           In Progress
3           Completed
4           In Progress

我还有一个PersonStatusHistory表,其中包含一个LoggedDate列以指示每个Person的状态更改何时发生。

PersonId   Status            LoggedDate
--------------------------------------------
1          Created           11/11/2022
1          In Progress       11/15/2022

2          Created           11/05/2022
2          In Progress       11/07/2022
2          Blocked           11/10/2022
2          In Progress       11/15/2022

3          Created           11/03/2022
3          In Progress       11/12/2022
3          Completed         11/17/2022

4          Created           11/01/2022
4          In Progress       11/03/2022
4          Blocked           11/05/2022
4          In Progress       11/10/2022
4          Blocked           11/12/2022
4          In Progress       11/15/2022

我想获取当前状态 = In Progress 的所有 Person 记录,它处于In Progress的天数减去它们被Blocked的天数。

预期结果应如下所示:

Emp Id      No of Days In Progress
--------------------------------------------
1           4
              > 11/18 (date today) - 11/15 (first In Progress LoggedDate)
              > 18 - 15 + 1 (current day) = 4 days
2           7
              > 11/18 (date today) minus 11/07 (first In Progress LoggedDate)
              > less the number of Blocked days 
              > 18 - 7 - 5 + 1 (current day) = 7
4           8 days
              > 11/18 (date today) minus 11/03 (first In Progress LoggedDate)
              > less the number of Blocked days (5 and 3 days) 
              > 18 - 3 - 5 - 3 + 1 (current day) = 8

我可以很容易地获得前 2 个所需的结果,但我很难弄清楚如何处理最后一个多次被阻止的用例。 到目前为止,这是我的代码

SELECT x.PersonId
       , (DATE_PART('day', CURRENT_DATE + 1) - DATE_PART('day', x.start_in_progress_date)
         - DATE_PART('day', end_blocked_date) - DATE_PART('day', x.start_blocked_date)
         ) as no_of_days_in_progress
FROM
(
  SELECT p.PersonId
         , MIN (psh.LoggedDate) AS start_in_progress_date
         , (SELECT MIN(psh.LoggedDate)
             FROM PersonStatusHistory psh2
             WHERE psh2.PersonId = p.PersonId
             AND psh2.Status = 'Blocked'
           ) as start_blocked_date
         , (SELECT MAX(psh.LoggedDate)
             FROM PersonStatusHistory psh3
             WHERE psh3.PersonId = p.PersonId
             AND psh3.Status = 'In Progress'
           ) as end_blocked_date
  FROM Person p
  INNER JOIN PersonStatusHistory psh
     ON psh.PersonId = p.PersonId
  WHERE p.Status = 'In Progress'
  GROUP BY p.PersonId
) x

我认为更好的方法是让状态更改事件结束(通过 LEAD)并仅总结“进行中”状态持续时间

select personid, status, sum(event_duration) + 1
from (
    SELECT personid, status , LoggedDate event_start,  
    coalesce (lead(LoggedDate,1) OVER( partition by personid ORDER BY LoggedDate),
    current_date) - LoggedDate event_duration,
    coalesce (lead(LoggedDate,1) OVER( partition by personid ORDER BY LoggedDate), current_date) as event_end
            from personstatushistory p 
            order by 1,3 ) q
 where status = 'In Progress'
 group by personid, status
 order by 1,2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM