Testé dans PostgreSQL; SQL utilise des exemples de valeurs de publication.
Aucune clé primaire n'est définie dans les tables fournies et le code ci-dessous en tient compte. Mieux serait d'ajouter des clés primaires et d'optimiser le code ci-dessous pour les exploiter: une meilleure qualité des données, une meilleure performance, un code plus propre, des gens plus heureux.
La suppression du préfixe tbl offre plus de flexibilité dans l'implémentation de la base de données. La table, la vue et le synonyme peuvent être utilisés de manière interchangeable sans impact sur le code qui fait référence à l'objet de base de données ou à la convention de dénomination.
/* period length as the desired number of consecutive days */
/* time window as the period to be analyzed */
SELECT DISTINCT
/* Consolidate employees with multiple periods */
a.employeeid
FROM
(SELECT
/* Generate all possible periods */
pk_c.workday begin_date,
/* End date for given period length; less one for closed boundaries */
LEAD(pk_c.workday,3-1,NULL) OVER (ORDER BY pk_c.workday) end_date
FROM (SELECT DISTINCT
/* No calendar PK, remove dupes; if PK, pull in-line view up */
c.workday
FROM sandbox.calendar c) pk_c
) p
INNER JOIN sandbox.absences a ON
/* Match absences with periods */
(a.absencedate BETWEEN p.begin_date AND p.end_date)
WHERE
/* In time window desired; exclude periods extending beyond boundaries */
(p.begin_date BETWEEN '2009-01-01' AND '2009-03-01'
AND /* NOT NULL exclusion implied for periods beyond calendar boundaries */
p.end_date BETWEEN '2009-01-01' AND '2009-03-01')
GROUP BY
a.employeeid,
/* Also group period, display only employee */
p.begin_date
HAVING
/* Number of absence days to match to the period length */
/* DISTINCT due to missing absences PK; if PK, drop DISTINCT */
COUNT(DISTINCT a.absencedate) = 3
;
Profitez. Version Stripped ci-dessous:
SELECT DISTINCT
a.employeeid
FROM
(SELECT
pk_c.workday begin_date,
LEAD(pk_c.workday,3-1,NULL) OVER (ORDER BY pk_c.workday) end_date
FROM (SELECT DISTINCT c.workday FROM sandbox.calendar c) pk_c) p
INNER JOIN sandbox.absences a ON
(a.absencedate BETWEEN p.begin_date AND p.end_date)
WHERE
(p.begin_date BETWEEN '2009-01-01' AND '2009-03-01'
AND p.end_date BETWEEN '2009-01-01' AND '2009-03-01')
GROUP BY
a.employeeid, p.begin_date
HAVING
COUNT(DISTINCT a.absencedate) = 3
;
question de Jeff sur l'insigne Woot pourrait être pertinente ici: http://stackoverflow.com/questions/1176011/sql-to-determine-minimum-sequential-days-of-access –