4

私の質問は次の質問に似ています:

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

違いは、内部クエリが2つのレコードを返し、外部クエリがあることです。

2つの日付範囲の間の日付のリストを表示するこのような内部クエリを作成する必要があります(実行されないこのクエリを試しています)。

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;
)

私の内部クエリは次の2行を返します:

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
4

4 に答える 4

5

素晴らしい質問です。これは本当に私を惹きつけました! 答えは、トムの投稿のさらに下に多かれ少なかれ埋もれていました。これは短いバージョンで、TestDR というテーブルを使用して範囲を定義しています。まず TestDR の内容:

SELECT * FROM TestDR;

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

次に、範囲内の日付ごとに 1 つの行を作成するクエリを示します。

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 日 (約 3 年) になると思われる場合は、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
于 2013-03-08T21:03:24.723 に答える
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

あなたのコードから、あなたは OO プログラマーであり、SQL に精通していないことがわかります。それはあなたのために多くのことをするので、それをコントロールしようとしないでください. 最適化機能の妨げになります。

これを誤解しないでください。私は同じ考え方を持っていました (私は機械よりも賢いと信じています)。

于 2013-03-08T21:19:29.183 に答える
0

外側のクエリで OR ステートメントを使用すると、日付を戻り値の Start_Date または End_Date のいずれかと等しくすることができます

AND (date = subQuery.Start_Date 
  OR date = subQuery.End_Date)
于 2013-03-08T19:27:45.257 に答える
0

日付の使用:

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

年次表と ISO 週数など... 開始日と終了日に任意の日付を使用します。接続日と接続日数は、その場でテーブルを生成するために使用されます。ハード構造を使用している場合は between 演算子を使用できます...:

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
于 2013-03-08T20:01:11.313 に答える