Anstatt nur die Länge der Semester oder die Lücken zwischen ihnen zu betrachten, können Sie mit generate_series()
, etwa so:
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
Diese weist jedem Tag innerhalb eines Semesters eine willkürliche, aber fortlaufende "Tagesnummer" zu, wobei alle Lücken zwischen den Semestern übersprungen werden.
Sie können dies dann als Unterabfrage/CTE JOIN
ed zu Ihrer Schülertabelle:Suchen Sie zuerst die "Tagesnummer" ihres Startdatums und fügen Sie dann 7 * n_weeks
hinzu um die "Tagesnummer" ihres Enddatums zu finden, und verbinden Sie sich schließlich wieder, um das tatsächliche Datum für diese "Tagesnummer" zu finden.
Dies setzt voraus, dass für Teilwochen keine besondere Handhabung erforderlich ist – d. h. wenn n_weeks
4 beträgt, muss der Studierende für 28 Tage immatrikuliert sein, die in die Dauer eines Semesters fallen. Der Ansatz könnte angepasst werden, um Wochen zu messen (überschreiten Sie 1 week
als letztes Argument für generate_series()
), mit dem zusätzlichen Schritt, herauszufinden, in welcher Woche das start_date
des Schülers ist fällt in.
Hier ist eine vollständige Abfrage (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