2013-07-13 45 views
2

我有一個變量長度爲'學期'的表,它們之間有一個可變的中斷,約束條件是'start_date'總是大於以前的' END_DATE':SQL-計算任意中斷的給定開始日期的結束日期

id start_date end_date 
    ----------------------------- 
    1 2012-10-01 2012-12-20 
    2 2013-01-05 2013-03-28 
    3 2013-04-05 2013-06-29 
    4 2013-07-10 2013-09-20 

和同學如下,其中可在任何給定時間學期內發生的開始日期的表:

id start_date n_weeks 
    ------------------------- 
    1 2012-11-15  25 
    2 2013-02-12  8 
    3 2013-03-02  12 

我試圖計算一個‘通過加入END_DATE’ '學生'在'學期'考慮到可變長度的中斷in-b在學期之間。

我可以在上學期的最後一天畫(即從以前行的END_DATE)和減法使用下面找到天學期在中間數:

SELECT start_date 
      , end_date 
      , lag(end_date) OVER() AS prev_end_date 
      , start_date - lag(end_date) OVER() AS days_break 
    FROM terms 
    ORDER BY start_date; 

顯然,如果有來僅僅是兩個術語,它只是一個在幾天內添加'break'(可能會轉換爲'weeks')的問題,從而將'end_date'延長同一段時間。

但是對於一個給定的學生,如果'n_weeks'跨度超過一個學期,那麼這樣的查詢怎麼可能結構化呢?

被敲我的頭在牆上的最後幾天,我會非常感謝任何幫助任何人都能夠提供....

非常感謝。

+0

下面是與數據和查詢測試出可能的解決方案所示的SQLFiddle:http://www.sqlfiddle.com/#!12/c487e/2 – IMSoP

回答

2

而不是隻盯着學期的長度或它們之間的差距,您可以生成使用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 

SQLFiddle demo

這爲一學期中的每一天分配了一個任意但順序的「日數」,跳過了所有學期之間的差距。

然後,您可以使用它作爲一個子查詢/ CTEJOIN版給學生的表:先找到自己的開始日期的「天數」,然後添加7 * n_weeks找到自己的結束日期的「天數」 ,最後回到找到該「日期編號」的實際日期。

這假設沒有特殊的處理需要部分星期 - 即如果n_weeks是4,學生必須註冊28天,這是在semeseter的持續時間內。該方法可以調整以測量周(通過1 week作爲generate_series()的最後一個參數),並追加查找學生的start_date屬於哪一週。

下面是一個完整的查詢(SQLFiddle demo here):

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 
+1

這簡直太棒了。我(和我的初期潰瘍)不能夠感謝你! (並感謝您的詳細解釋 - 非常有用...) – user908094

相關問題