Using Oracle 11g release 2, the following query gives an ORA-01790: expression must have same datatype as corresponding expression:
with intervals(time_interval)
In my opinion, "Recursive Subquery Factoring" is broken in 11g R2 for queries with date or timestamp column.
with test(X) as
(
select to_date('2010-01-01','YYYY-MM-DD') from dual
union all (
select (X + 1) from test where X <= to_date('2010-01-10','YYYY-MM-DD')
)
)
select * from test;
ORA-01790
use a cast to convert the datatype:
with test(X) as
(
select cast(to_date('2010-01-01','YYYY-MM-DD') as date) from dual
union all (
select (X + 1) from test where X <= to_date('2010-01-10','YYYY-MM-DD')
)
)
select * from test;
X
-------------------
2010-01-01 00:00:00
1 row selected
Casting a date into a date is helping, but where are the other results?
It gets even better...
Try it with another start date:
with test(X) as
(
select cast(to_date('2007-01-01','YYYY-MM-DD') as DATE) from dual
union all (
select (X + 1) from test where X <= to_date('2011-01-11','YYYY-MM-DD')
)
)
select * from test
where rownum < 10; -- important!
X
-------------------
2007-01-01 00:00:00
2006-12-31 00:00:00
2006-12-30 00:00:00
2006-12-29 00:00:00
2006-12-28 00:00:00
2006-12-27 00:00:00
2006-12-26 00:00:00
2006-12-25 00:00:00
2006-12-24 00:00:00
9 rows selected
Counting backwards? Why?
Update 14-Jan-2014: As a workaround, use the CTE starting with the end date and building the recursive CTE backwards, like this:
with test(X) as
(
select cast(to_date('2011-01-20','YYYY-MM-DD') as DATE) as x from dual
union all (
select cast(X - 1 AS DATE) from test
where X > to_date('2011-01-01','YYYY-MM-DD')
)
)
select * from test
Results:
| X |
|--------------------------------|
| January, 20 2011 00:00:00+0000 |
| January, 19 2011 00:00:00+0000 |
| January, 18 2011 00:00:00+0000 |
| January, 17 2011 00:00:00+0000 |
| January, 16 2011 00:00:00+0000 |
| January, 15 2011 00:00:00+0000 |
| January, 14 2011 00:00:00+0000 |
| January, 13 2011 00:00:00+0000 |
| January, 12 2011 00:00:00+0000 |
| January, 11 2011 00:00:00+0000 |
| January, 10 2011 00:00:00+0000 |
| January, 09 2011 00:00:00+0000 |
| January, 08 2011 00:00:00+0000 |
| January, 07 2011 00:00:00+0000 |
| January, 06 2011 00:00:00+0000 |
| January, 05 2011 00:00:00+0000 |
| January, 04 2011 00:00:00+0000 |
| January, 03 2011 00:00:00+0000 |
| January, 02 2011 00:00:00+0000 |
| January, 01 2011 00:00:00+0000 |
Test conducted with:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
Odd - works if you pass around varchar
s and convert (not cast):
WITH intervals(time_interval) AS
(SELECT to_char(TRUNC(systimestamp))
FROM dual
UNION ALL
SELECT to_char(to_timestamp(time_interval) + numtodsinterval(10, 'Minute'))
FROM intervals
WHERE to_timestamp(time_interval) < systimestamp
)
SELECT to_timestamp(time_interval) time_interval
FROM intervals
I have no idea about the type mismatch, but here is an alternative method to accomplish what I think you want (which works in 10gr2):
select base_time + numtodsinterval( 10*(level-1), 'Minute')
from (select trunc(systimestamp) base_time from dual)
connect by base_time + numtodsinterval( 10*(level-1), 'Minute') < systimestamp