5

Oracle 11g リリース 2 を使用すると、次のクエリは ORA-01790 を返します: 式は、対応する式と同じデータ型を持つ必要があります。

with intervals(time_interval) AS
 (select trunc(systimestamp)
    from dual
  union all
  select (time_interval + numtodsinterval(10, 'Minute'))
    from intervals
   where time_interval < systimestamp)
select time_interval from intervals;

このエラーは、UNION ALL の両方のサブクエリのデータ型が異なるデータ型を返していることを示しています。

各サブクエリで TIMESTAMP にキャストしても、同じエラーが発生します。

私は何が欠けていますか?

編集: CONNECT BY の代わりを探しているわけではありません。

4

3 に答える 3

8

私の意見では、「再帰サブクエリ ファクタリング」は、11g R2 で日付またはタイムスタンプ カラムを使用するクエリに対して壊れています。

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

キャストを使用してデータ型を変換します。

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

日付を日付にキャストすることは役に立ちますが、他の結果はどこにありますか?

それはさらに良くなります...

別の開始日で試してください:

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

逆算?なんで?

2014 年 1 月 14 日更新:回避策として、終了日から始まる CTE を使用し、次のように再帰 CTE を逆方向に構築します。

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 

結果:

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

テスト実施:

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
于 2010-05-17T17:36:54.570 に答える
2

奇数 - varchars を渡して変換する (キャストしない)場合に機能します。

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
于 2011-09-07T21:52:00.113 に答える
0

型の不一致についてはわかりませんが、必要だと思うことを達成するための代替方法を次に示します (これは 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
于 2010-04-06T19:50:18.820 に答える