【问题标题】:Query which will give a list of dates between two date ranges查询将给出两个日期范围之间的日期列表
【发布时间】:2013-03-08 19:24:48
【问题描述】:

我的问题类似于以下问题:

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

不同的是我的内部查询返回两条记录,而我有外部查询。

我需要编写类似这样的内部查询,它会给我一个两个日期范围之间的日期列表(我正在尝试这个不执行的查询)。

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

【问题讨论】:

标签: sql oracle oracle11g


【解决方案1】:

很好的问题 - 这个问题真的吸引了我!答案或多或少地隐藏在汤姆的帖子中。这是简短版本,使用名为 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

使用根据 Tom 的帖子改编的查询,您必须知道“播种”NUMS 查询的最大范围。他在他的例子中使用了 60,所以这就是我上面使用的。如果您认为子查询中的任何行都不会超过 60 天,那么这将起到作用。如果您认为最大值可能高达 1000 天(大约三年),请将 60 更改为 1000。我尝试了这个并查询了 2 1/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

【讨论】:

    【解决方案2】:

    对于您的问题,您无需列举日期。一个简单的 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。它对你有很大帮助,所以不要试图控制它。它会阻碍它的优化功能。

    不要误会,我也有同样的心态(相信自己比机器聪明)。

    【讨论】:

      【解决方案3】:

      在您的外部查询中使用 OR 语句,它允许您的日期等于返回的 Start_Date 或 End_Date

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

      【讨论】:

        【解决方案4】:

        使用您的日期:

        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
        

        【讨论】:

          猜你喜欢
          • 2023-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-15
          • 2020-02-20
          • 2011-11-10
          • 1970-01-01
          相关资源
          最近更新 更多