Thay vì chỉ xem xét độ dài của các học kỳ hoặc khoảng cách giữa chúng, bạn có thể tạo danh sách tất cả các ngày trong một học kỳ bằng cách sử dụng generate_series()
, như thế này:
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
Điều này chỉ định mỗi ngày trong học kỳ một "số ngày" tùy ý nhưng liên tục, bỏ qua tất cả khoảng cách giữa các học kỳ.
Sau đó, bạn có thể sử dụng điều này làm truy vấn phụ / CTE JOIN
ed vào bảng sinh viên của bạn:trước tiên hãy tìm "số ngày" của ngày bắt đầu của họ, sau đó thêm 7 * n_weeks
để tìm "số ngày" của ngày kết thúc của họ và cuối cùng kết hợp lại để tìm ngày thực tế cho "số ngày" đó.
Điều này giả định rằng không cần xử lý đặc biệt nào trong một phần tuần - tức là nếu n_weeks
là 4, học sinh phải ghi danh trong 28 ngày trong thời hạn của một người định trước. Phương pháp này có thể được điều chỉnh để đo lường số tuần (vượt qua 1 week
làm đối số cuối cùng cho generate_series()
), với bước bổ sung là tìm start_date
của học sinh vào tuần nào rơi vào.
Đây là một truy vấn hoàn chỉnh ( Bản trình diễn SQLFiddle tại đây ):
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