In plaats van alleen naar de lengtes van semesters of de hiaten ertussen te kijken, kunt u een lijst maken van alle datums die binnen een semester vallen met behulp van generate_series()
, zoals dit:
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
Dit wijst elke dag die tijdens een semester is een willekeurig maar opeenvolgend "dagnummer" toe, waarbij alle gaten tussen semesters worden overgeslagen.
U kunt dit vervolgens gebruiken als een subquery/CTE JOIN
ed aan uw tabel met studenten:zoek eerst het "dagnummer" van hun startdatum en voeg vervolgens 7 * n_weeks
toe om het "dagnummer" van hun einddatum te vinden en uiteindelijk terug te komen om de werkelijke datum voor dat "dagnummer" te vinden.
Dit veronderstelt dat er geen speciale behandeling nodig is voor gedeeltelijke weken - d.w.z. als n_weeks
is 4, moet de student 28 dagen ingeschreven staan die binnen de duur van een semester vallen. De aanpak kan worden aangepast om weken te meten (pass 1 week
als laatste argument voor generate_series()
), met de extra stap om te zoeken in welke week de start_date
. van de student valt in.
Hier is een volledige zoekopdracht (SQLFiddle-demo hier ):
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