我正在创建一个查询,根据年份给出两天之间的天数。实际上我有以下类型的日期范围
From Date: TO_DATE('01-Jun-2011','dd-MM-yyyy')
To Date: TO_DATE('31-Dec-2013','dd-MM-yyyy')
我的结果应该是:
Year Number of day
------------------------------
2011 XXX
2012 XXX
2013 XXX
我试过下面的查询
WITH all_dates AS
(SELECT start_date + LEVEL - 1 AS a_date
FROM
(SELECT TO_DATE ('21/03/2011', 'DD/MM/YYYY') AS start_date ,
TO_DATE ('25/06/2013', 'DD/MM/YYYY') AS end_date
FROM dual
)
CONNECT BY LEVEL <= end_date + 1 - start_date
)
SELECT TO_CHAR ( TRUNC (a_date, 'YEAR') , 'YYYY' ) AS YEAR,
COUNT (*) AS num_days
FROM all_dates
WHERE a_date - TRUNC (a_date, 'IW') < 7
GROUP BY TRUNC (a_date, 'YEAR')
ORDER BY TRUNC (a_date, 'YEAR') ;
我得到了确切的输出
Year Number of day
------------------------------
2011 286
2012 366
2013 176
我的问题是,如果我使用connect然后查询执行需要很长时间,因为我在表中有数百万条记录,因此我不想使用connect by子句
connect by
子句正在针对特定记录创建虚拟行。
非常感谢任何帮助或建议。
答案 0 :(得分:4)
根据您模糊的预期结果,我认为您希望这些日期之间的记录数量,而不是天数;但它还不清楚。由于您在问题中引用了一个表格,我假设您需要与表格数据相关的内容,而不仅仅是两个日期之间的日期,而这些日期根本不依赖于表格。 (我不知道connect by
子句引用意味着什么)。这应该会给你,如果你想要的话:
select extract(year from date_field), count(*)
from t42
where date_field >= to_date('01-Jun-2011', 'DD-MON-YYYY')
and date_field < to_date('31-Dec-2013') + interval '1' day
group by extract(year from date_field)
order by extract(year from date_field);
where
子句与两个日期之间的预期相同;我假设您的日期字段中可能有时间(即不是全部在午夜)并且您想要计算您范围内最后一个日期的所有记录。然后根据每条记录的年份对其进行分组和计数。
如果您想要在该范围内有记录的天数,那么您可以稍微改变计数:
select extract(year from date_field), count(distinct trunc(date_field))
...
答案 1 :(得分:1)
您可以使用以下功能来减少虚拟行的数量,只考虑其中的年份。您可以检查SQLFIDDLE以检查性能。
首先只考虑当年的开始日期和年末之间的天数 结束日期(如果是同年)
然后考虑从开始日期的明年到结束日期之前的年份之间的年份
最后考虑从结束日期年份开始到结束日期的天数
因此,我们不需要迭代开始日期和结束日期之间的所有日子,而只需要迭代年份
WITH all_dates AS
(SELECT (TO_CHAR(START_DATE,'yyyy') + LEVEL - 1) YEARS_BETWEEN,start_date,end_date
FROM
(SELECT TO_DATE ('21/03/2011', 'DD/MM/YYYY') AS start_date ,
TO_DATE ('25/06/2013', 'DD/MM/YYYY') AS end_date
FROM dual
)
CONNECT BY LEVEL <= (TO_CHAR(end_date,'yyyy')) - (TO_CHAR(start_date,'yyyy')-1)
)
SELECT DECODE(TO_CHAR(END_DATE,'yyyy'),YEARS_BETWEEN,END_DATE
,to_date('31-12-'||years_between,'dd-mm-yyyy'))
- DECODE(TO_CHAR(START_DATE,'yyyy'),YEARS_BETWEEN,START_DATE
,to_date('01-01-'||years_between,'dd-mm-yyyy'))+1,years_between
FROM ALL_DATES;
答案 2 :(得分:0)
在Oracle中,你可以对这样的日期执行加法和减法......
选择 TO_DATE('31 -Dec-2013','dd-MM-yyyy') - TO_DATE('01 -Jun-2011','dd-MM-yyyy') 来自双重日;
它将返回两个日期之间的日差....
答案 3 :(得分:0)
select to_date(2011, 'yyyy'), to_date(2012, 'yyyy'), to_date(2013, 'yyyy')
from dual;
TO_DATE(2011,'Y TO_DATE(2012,'Y TO_DATE(2013,'Y
--------------- --------------- ---------------
01-MAY-11 01-MAY-12 01-MAY-13
答案 4 :(得分:0)
select to_char(date_field,'yyyy'), count(*)
from your_table
where date_field between to_date('01-Jun-2011', 'DD-MON-YYYY')
and to_date('31-Dec-2013 23:59:59', 'DD-MON-YYYY hh24:mi:ss')
group by to_char(date_field,'yyyy')
order by to_char(date_field,'yyyy');