连续工作日的累计总和,当连续天数 = 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;
我有 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;