Вместо просто да разглеждате продължителността на семестрите или празнините между тях, можете да генерирате списък на всички дати, които са в рамките на един семестър, като използвате generate_series()
, като това:
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
Това присвоява на всеки ден, който е през семестъра, произволен, но последователен „номер на деня“, пропускайки всички празнини между семестрите.
След това можете да използвате това като подзаявка/CTE JOIN
ed във вашата таблица с ученици:първо намерете „номера на деня“ на началната им дата, след това добавете 7 * n_weeks
за да намерите „номера на деня“ на тяхната крайна дата и накрая да се присъедините, за да намерите действителната дата за този „номер на деня“.
Това предполага, че не е необходима специална обработка за частични седмици - т.е. ако n_weeks
е 4, студентът трябва да бъде записан за 28 дни, които са в рамките на продължителността на семестъра. Подходът може да се адаптира за измерване на седмици (преминете 1 week
като последен аргумент на generate_series()
), с допълнителната стъпка за намиране коя седмица е start_date
на ученика попада в.
Ето пълна заявка (демонстрация на SQLFiddle тук ):
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