连续工作日的累计总和,当连续天数 = 0 时重置为 1,每个 ID

A cumulative sum of consecutive workdays that resets to 1 when consecutive days = 0, per ID

我有 3 列:

工号(数字)

工作日(员工轮班的日期 yyyy-mm-dd)

is_consecutive_work_day(如果工作天数是连续的则为 1,否则为 0)

我需要第 4 个:Consecutive_work_days(is_consecutive_work_day 的累加和,当 is_consecutive_work_day = 0 时重置为 1)。因此,对于任何员工 ID,这将达到最大值 5。有些会有 1,2,3 其他的 1,2...等等

我没弄清楚的是如何写第 4 列 (consecutive_work_days)。不是如何写每个员工 ID 的连续总和,而是具体如何在每个员工 ID is_consecutive_work_day = 0 时重置为 1。

关于第 4 列,我可以请求您的帮助吗?谢谢。

您可以使用 window 功能。 lag() 允许您访问同一员工的前一个 day_of_work,您可以将其与当前 day_of_work 进行比较:如果有一天的差异,那么您可以设置 is_consecutive_work_day到 1.

select
    employee_id,
    day_of_work,
    case 
        when day_of_work 
            = lag(day_of_work) over(partition by employee_id order by day_of_work) 
                + interval 1 day
        then 1
        else 0
    end is_consecutive_work_day 
from mytable

要计算累计和,有点复杂。我们可以使用一些 gaps-and-island 技术将每条记录放在它所属的组中:基本上,每次 is_consecutive_work_day of 0 被满足时,一个新的组开始;然后我们可以对每个组做 window sum():

select 
    employee_id,
    day_of_work,
    is_consecutive_work_day,
    sum(is_consecutive_work_day) 
        over(partition by employee_id, grp order by day_of_work)
        consecutive_work_days 
from (
    select 
        t.*,
        sum(1 - is_consecutive_work_day) over(partition by employee_id order by day_of_work)  grp
    from (
        select
            t.*,
            case 
                when day_of_work 
                    = lag(day_of_work) over(partition by employee_id order by day_of_work) 
                        + interval 1 day
                then 1
                else 0
            end is_consecutive_work_day 
        from mytable t
    ) t
) t

虽然这看起来像是一个间隙和孤岛问题,但有一个更简单的解决方案。只需计算最大先前值 0 并取日期差。

唯一需要注意的是是否有 none。

那就是:

select t.*,
       datediff(day_of_work,
                coalesce(max(case when is_consecutive_work_day = 0 then day_of_work end) over (partition by employee_id),
                         date_add(min(day_of_work) partition by employee_id), 1)
                        )
               ) as fourth_column
from t;