Plutôt que de simplement regarder la durée des semestres ou les écarts entre eux, vous pouvez générer une liste de toutes les dates d'un semestre en utilisant generate_series()
, comme ceci :
SELECT
row_number() OVER () as day_number,
day
FROM
(
SELECT
generate_series(start_date, end_date, '1 day') as day
FROM
semesters
) as day_series
ORDER BY
day
Cela attribue à chaque jour d'un semestre un "numéro de jour" arbitraire mais séquentiel, en sautant tous les écarts entre les semestres.
Vous pouvez ensuite l'utiliser comme sous-requête/CTE JOIN
à votre table d'étudiants :trouvez d'abord le "numéro de jour" de leur date de début, puis ajoutez 7 * n_weeks
pour trouver le "numéro de jour" de leur date de fin, et enfin revenez pour trouver la date réelle de ce "numéro de jour".
Cela suppose qu'il n'y a pas de traitement spécial nécessaire pour les semaines partielles - c'est-à-dire si n_weeks
est de 4, l'étudiant doit être inscrit pendant 28 jours qui sont dans la durée d'un semestre. L'approche pourrait être adaptée pour mesurer les semaines (passer 1 week
comme dernier argument de generate_series()
), avec l'étape supplémentaire de trouver quelle semaine la start_date
de l'étudiant tombe dans.
Voici une requête complète (Démo SQLFiddle ici ):
WITH semester_days AS
(
SELECT
semester_id,
row_number() OVER () as day_number,
day_date::date
FROM
(
SELECT
id as semester_id,
generate_series(start_date, end_date, '1 day') as day_date
FROM
semesters
) as day_series
ORDER BY
day_date
)
SELECT
S.id as student_id,
S.start_date,
SD_start.semester_id as start_semester_id,
S.n_weeks,
SD_end.day_date as end_date,
SD_end.semester_id as end_semester_id
FROM
students as S
JOIN
semester_days as SD_start
On SD_start.day_date = S.start_date
JOIN
semester_days as SD_end
On SD_end.day_number = SD_start.day_number + (7 * S.n_weeks)
ORDER BY
S.start_date