Piuttosto che guardare solo la durata dei semestri o gli intervalli tra di loro, potresti generare un elenco di tutte le date che si trovano all'interno di un semestre utilizzando generate_series()
, in questo modo:
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
Questo assegna a ogni giorno che è durante un semestre un "numero del giorno" arbitrario ma sequenziale, saltando tutti gli intervalli tra i semestri.
Puoi quindi usarlo come sottoquery/CTE JOIN
ed alla tua tabella degli studenti:trova prima il "numero del giorno" della loro data di inizio, quindi aggiungi 7 * n_weeks
per trovare il "numero del giorno" della loro data di fine e infine riconnettersi per trovare la data effettiva per quel "numero del giorno".
Ciò presuppone che non sia necessaria una gestione speciale per le settimane parziali, ad esempio se n_weeks
è 4, lo studente deve essere iscritto per 28 giorni che rientrano nella durata di un semestre. L'approccio potrebbe essere adattato per misurare le settimane (passa 1 week
come ultimo argomento per generate_series()
), con il passaggio aggiuntivo di trovare in quale settimana la start_date
dello studente cade dentro.
Ecco una query completa (Demo SQLFiddle qui ):
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