我的问题类似于以下问题:
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;
)
我的内部查询返回以下两行:
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
答案 0 :(得分: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
根据Tom的帖子调整查询,您必须知道“种子”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
答案 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
从您的代码中,我可以说您必须是OO程序员并且不熟悉SQL。它为你做了很多,所以不要试图控制它。它会阻碍它的优化功能。
不要以错误的方式采取这种做法,我有同样的心态(相信我比机器更聪明)。
答案 2 :(得分:0)
在您的外部查询中使用OR语句,它允许您的日期等于返回Start_Date或End_Date
AND (date = subQuery.Start_Date
OR date = subQuery.End_Date)
答案 3 :(得分: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周等...使用开始日期和结束日期的任何日期。连接和之间的天数用于动态生成表。如果使用硬结构,您可以在运算符之间使用......:
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