I stedet for blot at se på længden af semestre eller hullerne mellem dem, kan du generere en liste over alle datoer, der er inden for et semester, ved hjælp af generate_series()
, sådan her:
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
Dette tildeler hver dag, der er i løbet af et semester, et vilkårligt, men sekventielt "dagnummer", hvorved alle hullerne mellem semestrene springes over.
Du kan derefter bruge dette som en underforespørgsel/CTE JOIN
ed til din tabel over elever:find først "dagnummeret" for deres startdato, og tilføj derefter 7 * n_weeks
for at finde "dagnummeret" for deres slutdato, og slutteligt slutte sig til for at finde den faktiske dato for det "dagnummer".
Dette forudsætter, at der ikke er behov for særlig håndtering i delvise uger - dvs. hvis n_weeks
er 4, skal den studerende være indskrevet i 28 dage, som ligger inden for varigheden af et semester. Fremgangsmåden kunne tilpasses til at måle uger (bestå 1 week
som det sidste argument til generate_series()
), med det ekstra trin at finde, hvilken uge elevens start_date
falder i.
Her er en komplet forespørgsel (SQLFiddle-demo her ):
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