【问题标题】:A cumulative sum of consecutive workdays that resets to 1 when consecutive days = 0, per ID连续工作日的累计总和,当连续天数 = 0 时重置为 1,每个 ID
【发布时间】:2020-05-31 17:36:49
【问题描述】:

我有 3 列:

员工 ID(数字)

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

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

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

想不通的是如何写第四列(consecutive_work_days)。不是如何为每个员工 id 写入连续总和,而是具体如何在 is_consecutive_work_day = 0 每个员工 id 时重置为 1。

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

【问题讨论】:

    标签: sql database window-functions impala gaps-and-islands


    【解决方案1】:

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

    唯一需要注意的是如果没有。

    那就是:

    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;
    

    【讨论】:

      【解决方案2】:

      您可以使用窗口函数。 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 技术将每条记录放入它所属的组中:基本上,每次遇到0is_consecutive_work_day,就会开始一个新组;然后我们可以在每个组上创建一个窗口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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-07
        • 2018-04-25
        • 1970-01-01
        • 2021-04-27
        • 2018-10-30
        • 2023-03-12
        • 2012-10-18
        相关资源
        最近更新 更多