PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

SQL -- calcolo delle date di fine da una data di inizio data con interruzioni arbitrarie

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

(Demo di SQLFiddle )

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