在一组记录中找到“连续组”的一种方法是使用变量来跟踪每行之间的差异并开发将连续范围组合在一起的分组。在下面的示例中,我使用三个变量来跟踪用于生成组的足够信息:
- @curEmployee - 从上一条记录中跟踪当前员工,并与当前记录上的员工进行比较,以了解我们何时切换到不同的员工,该员工自动成为另一个分组
- @curEndDate - 跟踪上一条记录的最后结束日期,因此可以将其与当前记录的开始日期进行比较,以查看当前记录是否与上一条记录属于同一“组” - 也就是说,它是具有先前记录的连续就业的一部分
- @curGroup - 这是将行分隔为代表连续就业的单独“组”的关键变量。逻辑是,当且仅当以下两个条件为真时,应该认为一行与上一行是连续的:两行具有相同的员工编号,并且上一行的结束日期距离上一行不到 21 天。当前行。
- 注意:您可能想要验证边缘条件,即,是否恰好相隔 20/21/22 天将被视为连续就业,并调整以下逻辑。
这是计算这些组的示例查询。select
有几点需要注意:变量赋值的顺序很重要,因为它们在列表中是从上到下分配的。我们需要先进行赋值@curGroup
,以便它仍然具有上一条记录的值@curEmployee
以供@curEndDate
使用。其次,该子句非常重要,以确保我们在比较先前记录和当前记录时,它们是彼此最接近的两条记录。如果我们以随机顺序查看记录,它们很可能最终都成为单独的组。order by
select
e.employee, e.`start date`, e.`end date`
,@curGroup :=
case when employee = @curEmployee
and @curEndDate + INTERVAL 21 DAY >= e.`start date`
then @curGroup
else @curGroup + 1
end as curGroup
,@curEmployee := employee as curEmployee
,@curEndDate := e.`end date` as curEndDate
from
employment e
JOIN (SELECT @curEmployee := 0, @curEndDate := NULL, @curGroup := 0) r
order by e.employee, e.`start date`
示例结果 ( DEMO ) - 注意前两行是如何CURGROUP
保持不变的1
,因为它们彼此相隔 21 天并代表连续就业,而最后两行被标识为单独的组号:
| EMPLOYEE | START DATE | END DATE | CURGROUP | CUREMPLOYEE | CURENDDATE |
-------------------------------------------------------------------------------------------------------------------------------
| 1 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 | 1 | 1 | 2012-11-05 00:00:00 |
| 1 | November, 08 2012 00:00:00+0000 | January, 25 2013 00:00:00+0000 | 1 | 1 | 2013-01-25 00:00:00 |
| 2 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 | 2 | 2 | 2012-11-05 00:00:00 |
| 2 | November, 30 2012 00:00:00+0000 | January, 02 2013 00:00:00+0000 | 3 | 2 | 2013-01-02 00:00:00 |
现在我们已经建立了作为连续就业一部分的记录组,我们只需要按这些组编号进行分组,并找到输出的最小和最大日期范围:
select
employee,
min(`start date`) as `start date`,
max(`end date`) as `end date`
from (
select
e.employee, e.`start date`, e.`end date`
,@curGroup :=
case when employee = @curEmployee
and @curEndDate + INTERVAL 21 DAY >= e.`start date`
then @curGroup
else @curGroup + 1
end as curGroup
,@curEmployee := employee as curEmployee
,@curEndDate := e.`end date` as curEndDate
from
employment e
JOIN (SELECT @curEmployee := 0, @curEndDate := NULL, @curGroup := 0) r
order by e.employee, e.`start date`
) as T
group by curGroup
示例结果(演示):
| EMPLOYEE | START DATE | END DATE |
--------------------------------------------------------------------------------
| 1 | October, 01 2012 00:00:00+0000 | January, 25 2013 00:00:00+0000 |
| 2 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 |
| 2 | November, 30 2012 00:00:00+0000 | January, 02 2013 00:00:00+0000 |