2013-03-08 132 views
4

我的問題是類似以下問題:查詢,這將給兩個日期之間的日期範圍的列表

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:14582643282111

不同的是我內心的查詢返回兩個記錄,我有外部查詢。

我需要寫內部查詢這樣會給我一個日期列表之間兩個日期範圍(我正在嘗試這個查詢WHCIH不執行)。下面兩行

Select * from outerTable where my_date in 
( 
    select to_date(r.REQ_DATE) + rownum -1 
    from all_objects, (MY_INNER_QUERY Where ID =100) r 
    where rownum <= to_date(r.DUE_DATE,'dd-mon-yyyy')-to_date(r.REQ_DATE,'dd-mon-yyyy')+1; 
) 

我內心的查詢返回:

Select * from innerTable Where ID =100 


    Start date   end date 
    3/19/2013   3/21/2013 
    3/8/2013    3/8/2013 

所以我需要內部查詢將以下日期返回外部查詢:

3/19/2013 
    3/20/2013 
    3/21/2013 
    3/8/2013 
+1

2013年3月20日到來的原因是什麼? – 2013-03-08 19:29:09

回答

4

偉大的問題 - 這真的吸引了我!答案或多或少地埋在湯姆的職位上。以下是短版本,使用名爲TestDR的表來定義範圍。首先TestDR內容:

SELECT * FROM TestDR; 

STARTDATE ENDDATE 
--------- --------- 
19-MAR-13 21-MAR-13 
08-MAR-13 08-MAR-13 

現在的查詢爲範圍內的每個日期創建一個行:

WITH NUMS AS (
    SELECT LEVEL-1 DaysToAdd 
    FROM DUAL 
    CONNECT BY LEVEL <= 60 
) 
SELECT StartDate + DaysToAdd TheDate 
FROM TestDR 
CROSS JOIN NUMS 
WHERE TestDR.EndDate - TestDR.StartDate + 1 > DaysToAdd 
ORDER BY 1 

THEDATE 
--------- 
08-MAR-13 
19-MAR-13 
20-MAR-13 
21-MAR-13 

隨着改編自湯姆張貼的查詢,你必須知道的最大範圍會進入「種子」NUMS查詢。他在他的例子中使用了60,所以這就是我上面使用的。如果你不認爲你的子查詢中的任何行將會有超過60天的範圍,那麼這將做到這一點。如果您認爲最長時間可能高達1000天(大約三年),那麼將其從60改爲1000.我嘗試了這種方法,並詢問了2年半的時間,結果是即時的。

如果您想指定確切的「種子」計數,您可以計算它,如果你願意使查詢更復雜一點。以下是我可以用我的TestDR表做到這一點:

WITH NUMS AS (
    SELECT LEVEL-1 DaysToAdd 
    FROM DUAL 
    CONNECT BY LEVEL <= (
    SELECT MAX(EndDate - StartDate + 1) 
    FROM TestDR) 
) 
SELECT ... and the rest of the query as above 
0

在你的外部查詢使用OR語句,它允許您的日期等於返回Start_Date或End_Date

AND (date = subQuery.Start_Date 
    OR date = subQuery.End_Date) 
0

使用日期:日期和ISO周等

SELECT smth... FROM some_tab 
WHERE your_date IN 
(-- remove unnecessary columns, leave only what you select in outer query 
    -- or select * 
SELECT start_date 
, TRUNC(start_date, 'iw')     wk_starts 
, TRUNC(start_date, 'iw') + 7 - 1/86400 wk_ends 
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk# 
FROM 
(
SELECT (start_date-1) + LEVEL AS start_date 
FROM 
(-- replace this part with selecting your start and end dates from your table -- 
SELECT to_date('03/21/2013', 'MM/DD/YYYY') end_date 
    , to_date('03/19/2013', 'MM/DD/YYYY') start_date 
FROM dual 
) 
CONNECT BY LEVEL <= (end_date - start_date) 
) 
) -- your outer query ends -- 
/

START_DATE WK_STARTS WK_ENDS    ISO_WK# 
---------------------------------------------------------- 
3/19/2013 3/18/2013 3/24/2013 11:59:59 PM 12 
3/20/2013 3/18/2013 3/24/2013 11:59:59 PM 12 

年度表...使用的開始和結束日期的任何日期。連接方式和間隔天數用於生成表格。如果使用硬結構,您可以在運營商之間使用...:

SELECT start_date 
, TRUNC(start_date, 'iw')     wk_starts 
, TRUNC(start_date, 'iw') + 7 - 1/86400 wk_ends 
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk# 
FROM 
(-- This part simplifies above formatting and optional -- 
SELECT (start_date-1) + LEVEL AS start_date 
    FROM 
    (-- Replace start/end dated with any dates -- 
    SELECT TRUNC(ADD_MONTHS (SYSDATE, 12), 'Y')-1 end_date 
     , TRUNC(SYSDATE, 'YEAR')     start_date 
    FROM dual 
) 
    CONNECT BY LEVEL <= (end_date - start_date) -- number of days between dates 
) 
/

START_DATE WK_STARTS WK_ENDS     ISO_WK# 
----------------------------------------------------------- 
1/1/2013  12/31/2012 1/6/2013 11:59:59 PM  1 
1/2/2013  12/31/2012 1/6/2013 11:59:59 PM  1 
1/3/2013  12/31/2012 1/6/2013 11:59:59 PM  1 
... 
12/28/2013 12/23/2013 12/29/2013 11:59:59 PM 52 
12/29/2013 12/23/2013 12/29/2013 11:59:59 PM 52 
12/30/2013 12/30/2013 1/5/2014 11:59:59 PM  1 
3

對於你的問題,你不必列舉的日期。一個簡單的JOIN就足夠了。

SELECT o.* 
    FROM outerTable o 
INNER JOIN innerTable i 
    ON i.ID = 100 
    AND o.my_date BETWEEN i.REQ_DT and i.DUE_DT 

從你的代碼中,我可以告訴你必須是面向對象的程序員,而不熟悉SQL。它爲你做了很多,所以不要試圖控制它。它會阻礙它的優化功能。

不要以錯誤的方式,我有相同的心態(相信我比機器更聰明)。