Cette réponse a quelques hypothèses.
hypothèses
L'ensemble de données est seulement pour un employé à la fois. Si ce n'est pas, et il y a une autre colonne, comme EmployeeID
, alors vous voulez vouloir spécifier que dans une clause partition by
à l'intérieur de la clause over
où mes commentaires le dénotent.
Que les EmployeeStatusCatalog
valeurs sont les suivantes:
- A: Actif
- L: Laissez (d'absence)
- I: inactif
Qu'une « location "ou la transaction" Rehire "est considérée comme ayant lieu soit au statut A
initial, soit après qu'un statut I
est terminé .
Configuration des données de l'échantillon
ne comprenait pas la colonne EmployeeStatusId
, mon hypothèse est que ce n'est pas pertinent de créer le résultat attendu.
declare @employee table
(
EffectiveStartDate date not null
, EffectiveEndDate date not null
, EmployeeStatusCatalog char(1) not null
)
insert into @employee
values ('2008-02-29', '2016-05-31', 'A')
, ('2016-06-01', '2016-06-30', 'A')
, ('2016-07-01', '2016-07-30', 'L')
, ('2016-07-31', '2016-09-02', 'A')
, ('2016-09-03', '2016-10-09', 'I')
, ('2016-10-10', '2016-11-01', 'A')
, ('2016-11-02', '2016-12-02', 'L')
, ('2016-12-03', '2016-12-05', 'I')
, ('2016-12-06', '2016-12-06', 'A')
, ('2016-12-07', '2017-01-01', 'L')
, ('2017-01-02', '9999-12-31', 'A')
Réponse
Comme vous pouvez ou ne pouvez pas savoir, cela est un scénario gaps and islands classique. Où chaque segment entre les dates Hire/Rehire est une île (pas de lacunes dans cet exemple).
J'ai utilisé un CTE pour déplacer l'état I
avant une ligne (via LAG fonction), puis obtenir le compte courant du nombre de lignes I
pour donner à chaque île un nombre « ID ».
Après cela, utilisé une fonction min
, lors du partitionnement par le numéro d'îlot, afin de déterminer le EffectiveStartDate
minimum pour chaque îlot.
; with inactive_dts as
(
--move the I status forward one row
select e.EffectiveStartDate
, e.EffectiveEndDate
, e.EmployeeStatusCatalog
, lag(e.EmployeeStatusCatalog, 1, 'A') over (/*partion by here*/ order by e.EffectiveStartDate asc) as prev_status
from @employee as e
where 1=1
)
, active_island_nbr as
(
--get the running count of the number of I rows
select a.EffectiveStartDate
, a.EffectiveEndDate
, a.EmployeeStatusCatalog
, a.prev_status
, sum(case a.prev_status when 'I' then 1 else 0 end) over (/*partition by here*/ order by a.EffectiveStartDate asc) as ActiveIslandNbr
from inactive_dts as a
)
select min(a.EffectiveStartDate) over (partition by a.ActiveIslandNbr) as HireRehireDate
, a.EffectiveStartDate
, a.EffectiveEndDate
, a.EmployeeStatusCatalog
from active_island_nbr as a
Résultats
HireRehireDate EffectiveStartDate EffectiveEndDate EmployeeStatusCatalog
2008-02-29 2008-02-29 2016-05-31 A
2008-02-29 2016-06-01 2016-06-30 A
2008-02-29 2016-07-01 2016-07-30 L
2008-02-29 2016-07-31 2016-09-02 A
2008-02-29 2016-09-03 2016-10-09 I
2016-10-10 2016-10-10 2016-11-01 A
2016-10-10 2016-11-02 2016-12-02 L
2016-10-10 2016-12-03 2016-12-05 I
2016-12-06 2016-12-06 2016-12-06 A
2016-12-06 2016-12-07 2017-01-01 L
2016-12-06 2017-01-02 9999-12-31 A
Je voulais juste vérifier en arrière et voir si la réponse que je donnais était assez clair, ou si vous avez d'autres questions à ce sujet. Si la réponse est ce que vous cherchiez, allez-y et acceptez la réponse (cochez la case par la réponse) pour laisser ceux qui trébuchent sur cette question plus tard que c'était en fait la solution. – tarheel