一連のレコードの中から「連続グループ」を見つける方法の 1 つは、変数を使用して各行の違いを追跡し、連続範囲を組み合わせたグループを作成することです。以下の例では、3 つの変数を使用して、グループを生成するのに十分な情報を追跡しています。
- @curEmployee - 前のレコードから現在の従業員を追跡し、現在のレコードの従業員と比較して、別の従業員にいつ切り替えたかを判断します。別の従業員は自動的に別のグループになります
- @curEndDate - 前のレコードの最後の終了日を追跡するため、現在のレコードの開始日と比較して、現在のレコードが前のレコードと同じ「グループ」に属しているかどうかを確認できます。つまり、前歴のある継続雇用の一環
- @curGroup - これは、継続的な雇用を表す個別の「グループ」に行を分離するキー変数です。ロジックは、次の 2 つの条件が真である場合にのみ、行が前の行と連続していると見なされる必要があるということです: 2 つの行の従業員番号が同じで、前の行の終了日が日付から 21 日未満である現在の行。
- 注: 境界条件、つまり、正確に 20/21/22 日の間隔が継続雇用と見なされるかどうかを検証し、以下のロジックを微調整することをお勧めします。
これらのグループを計算するサンプル クエリを次に示します。select
注意すべき点がいくつかあります。変数はリストの上から下に割り当てられるため、変数の割り当ての順序は重要です。前のレコードの値と前のレコードから@curGroup
の値を引き続き使用できるように、最初に割り当てる必要があります。次に、前のレコードと現在のレコードを比較するときに、それらが互いに最も近い 2 つのレコードであることを確認するために、句は非常に重要です。レコードをランダムな順序で見ると、最終的にすべて別々のグループになる可能性があります。@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 ) -最初の 2 行CURGROUP
が にとどまって1
いることに注意してください。これらは互いに 21 日以内にあり、継続的な雇用を表しているためです。最後の 2 行は別のグループ番号として識別されます。
| 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 |