par , 27/11/2022 à 16h11 (2156 Affichages)
5e exercice, dates d'anniversaire. En voici un exercice intéressant, son énoncé :
Ce problème "date d'anniversaire" est venu de mon patron, qui m'a dit un jour, comme ça, tout de go, "je voudrais envoyer une carte pour chacun de mes clients afin de lui souhiater un bon anniversaire..."
Fastoche, me suis-je dis. Hélas, j'ai du piannoter un bon moment avant d'arriver à trouver une solution honnête.
Sauriez vous trouver aussi bien, sinon mieux encore que ce que j'ai fait ???
La difficulté est que la nature du prédicat n'est pas la même selon la relation entre les bornes de l'intervalle de dates.
Exemples :
Je cherche les dates de naissance entre le 20/12 et le 31/12, le prédicat sera :
1 2
| ...
WHERE birthday_month_day BETWEEN '12-20' AND '12-30' |
Je cherche les dates de naissance entre le 25/12 et le 05/01 (de l'année suivante), le prédicat sera :
1 2
| ...
WHERE birthday_month_day >= '12-25' OR birthday_month_day <= '01-05' |
Il y a probablement d'autres approches, comme modifier le mois de l'année suivante ("01-05" deviendrait "13-05") ou modifier les années de naissance, mais ajuster la nature du prédicat plutôt que les valeurs me semble plus simple.
Le tri aussi pose problème, car on veut trier les anniversaires dans leur ordre d'arrivée, il faut donc calculer des groupes.
Ma solution :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| WITH DATASET AS (
-- Préparation des données nécessaires
SELECT ALL
CLI_NOM, CLI_DATE_NAISSANCE,
'12-21' AS PERIOD_BEGIN, -- Borne inférieure "MM-JJ" de recherche (param.)
'01-20' AS PERIOD_END, -- Borne supérieure "MM-JJ" de recherche (param.)
DATE_FORMAT(CLI_DATE_NAISSANCE, '%m-%d') AS BMD -- "MM-JJ" de naissance
FROM T_CLIENT_CLI
)
SELECT ALL CLI_NOM, CLI_DATE_NAISSANCE
FROM DATASET
WHERE
CASE
WHEN PERIOD_BEGIN <= PERIOD_END THEN BMD BETWEEN PERIOD_BEGIN AND PERIOD_END
ELSE BMD >= PERIOD_BEGIN OR BMD <= PERIOD_END
END
ORDER BY
CASE BMD >= PERIOD_BEGIN WHEN TRUE THEN 1 ELSE 2 END ASC,
BMD ASC
; |