2009-01-25 62 views
1

考慮三個表日期(日期ADATE,撲滅布爾),天(rangeId INT,天INT,數量int)和量程(rangeId INT,的startDate日)在甲骨文有效的連接與 「相關」 子查詢

我想要加入這些以便Range與來自aDate = startDate的日期連接,其中doUse = 1,每天在Days中。

給定一個範圍,可能做這樣的事情

SELECT rangeId, aDate, CASE WHEN doUse = 1 THEN qty ELSE 0 END AS qty 
FROM (
    SELECT aDate, doUse, SUM(doUse) OVER (ORDER BY aDate) day 
    FROM Dates 
    WHERE aDate >= :startDAte 
) INNER JOIN (
    SELECT rangeId, day,qty 
    FROM Days 
    WHERE rangeId = :rangeId 
) USING (day) 
ORDER BY day ASC 

我想要做的就是查詢有效範圍內的所有範圍,不只是一個。

問題是,連接值「日」取決於要計算的範圍startDate,這給我在制定查詢時遇到了一些麻煩。

請記住日期表非常大,所以我想避免從表中的第一個日期計算日期值,而每個範圍日期不應超過100天左右。

編輯:樣本數據

Dates       Days 
aDate  doUse    rangeId  day  qty 
2008-01-01 1     1   1  1 
2008-01-02 1     1   2  10 
2008-01-03 0     1   3  8 
2008-01-04 1     2   1  2 
2008-01-05 1     2   2  5 

Ranges 
rangeId  startDate 
1   2008-01-02 
2   2008-01-03 


Result 
rangeId  aDate  qty 
1   2008-01-02 1 
1   2008-01-03 0 
1   2008-01-04 10 
1   2008-01-05 8 
2   2008-01-03 0 
2   2008-01-04 2 
2   2008-01-05 5 
+0

請問您可以填寫一些示例數據,您希望得到什麼樣的結果? – Quassnoi 2009-01-25 22:20:29

回答

3

試試這個:

SELECT rt.rangeId, aDate, CASE WHEN doUse = 1 THEN qty ELSE 0 END AS qty 
FROM (
    SELECT * 
    FROM (
     SELECT r.*, t.*, SUM(doUse) OVER (PARTITION BY rangeId ORDER BY aDate) AS span 
     FROM (
      SELECT r.rangeId, startDate, MAX(day) AS dm 
      FROM Range r, Days d 
      WHERE d.rangeid = r.rangeid 
      GROUP BY 
       r.rangeId, startDate 
      ) r, Dates t 
     WHERE t.adate >= startDate 
     ORDER BY 
      rangeId, t.adate 
     ) 
    WHERE 
     span <= dm 
    ) rt, Days d 
WHERE d.rangeId = rt.rangeID 
    AND d.day = GREATEST(rt.span, 1) 

PS在我看來,唯一的點,以保持所有這些Dates數據庫是讓註明假期連續日曆。

您可以用以下結構產生任意長度的Oracle中的日曆:

SELECT :startDate + ROWNUM 
FROM dual 
CONNECT BY 
     1 = 1 
WHERE rownum < :length 

,只保留假期Dates。一個簡單的加入會告訴你哪些是假期,哪些不是假期。

+1

爲什麼?爲什麼一遍又一遍地產生一些東西。日期表非常有用......您可以有假期專欄,我們擁有100個假期日曆,您可以在週末,工作日,第一天,最後一天,促銷銷售中添加專欄,並且您可以將它們全部位圖化,以便您可以ad hoc q's – 2009-01-26 18:13:45

1

好了,也許我已經找到一種方法。成纔是這樣的:

SELECT irangeId, aDate + sum(case when doUse = 1 then 0 else 1) over (partionBy rangeId order by aDate) as aDate, qty 
FROM Days INNER JOIN (
    select irangeId, startDate + day - 1 as aDate, qty 
    from Range inner join Days using (irangeid) 
) USING (aDate) 

現在我只需要一種方法來填充缺少的日期......

編輯:不,這樣意味着我將錯過最後日期的撲滅vaue。 ..