Spíše než jen prohlížet délky semestrů nebo mezery mezi nimi můžete vygenerovat seznam všech dat, která jsou v rámci semestru, pomocí generate_series()
, takto:
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
To přiřadí každému dni, který je během semestru, libovolné, ale sekvenční „číslo dne“, čímž se vynechají všechny mezery mezi semestry.
Toto pak můžete použít jako dílčí dotaz/CTE JOIN
ed do tabulky studentů:nejprve najděte „číslo dne“ jejich data zahájení a poté přidejte 7 * n_weeks
najít "číslo dne" jejich koncového data a nakonec se připojit, abyste našli skutečné datum pro toto "číslo dne".
To předpokládá, že pro částečné týdny není potřeba žádná zvláštní manipulace – tj. pokud n_weeks
je 4, student musí být zapsán na 28 dní, které jsou v rámci semestru. Tento přístup by mohl být přizpůsoben pro měření týdnů (projděte 1 week
jako poslední argument pro generate_series()
), s dalším krokem zjištění, který týden má student start_date
spadá do.
Zde je úplný dotaz (Ukázka SQLFiddle zde ):
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