【问题标题】:ORACLE (11.2.0.1.0) - Recursive CTE with a date expressionORACLE (11.2.0.1.0) - 带有日期表达式的递归 CTE
【发布时间】:2017-11-28 07:49:51
【问题描述】:

以下问题的正确答案:

  • 如果我没记错的话,这是在 11.2.0.3 或更高版本中修复的错误。 (无论如何,11.2.0.1 不再受支持。11.2.0.4 是唯一仍受支持的 11.2 版本)– @a_horse_with_no_name
  • 错误编号为 11840579,已在 11.2.0.3 和 12.1.0.1 中修复 – @a_horse_with_no_name

问题

我有一张桌子

CREATE TABLE test(
  from_date date,
  to_date date
);

INSERT INTO test(from_date,to_date)
--VALUES('20171101','20171115');
VALUES(TO_DATE('20171101','YYYYMMDD'),TO_DATE('20171115','YYYYMMDD'));

Oracle 中的以下查询仅返回一行(预计为 15 行)

WITH dateCTE(from_date,to_date,d,i) AS(
  SELECT from_date,to_date,from_date AS d,1 AS i
  FROM test

  UNION ALL

  SELECT from_date,to_date,d+INTERVAL '1' DAY,i+1
  FROM dateCTE
  WHERE d<to_date
)
SELECT d,i
FROM dateCTE

SQL 小提琴 - http://sqlfiddle.com/#!4/36907/8

为了测试,我将条件更改为i&lt;10

WITH dateCTE(from_date,to_date,d,i) AS(
  SELECT from_date,to_date,from_date AS d,1 AS i
  FROM test

  UNION ALL

  SELECT from_date,to_date,d+INTERVAL '1' DAY,i+1
  FROM dateCTE
  --WHERE d<to_date
  WHERE i<10 -- exit condition
)
SELECT d,i
FROM dateCTE

并得到下一个结果

| D          | I  |
|------------|----|
| 2017-11-01 |  1 |
| 2017-10-31 |  2 |
| 2017-10-30 |  3 |
| 2017-10-29 |  4 |
| 2017-10-28 |  5 |
| 2017-10-27 |  6 |
| 2017-10-26 |  7 |
| 2017-10-25 |  8 |
| 2017-10-24 |  9 |
| 2017-10-23 | 10 |

为什么这个递归查询在 Oracle 中返回了错误的结果?

SQL 小提琴 - http://sqlfiddle.com/#!4/36907/5

我在 SQLServer 中运行了类似的查询,得到了正确的结果

WITH dateCTE(from_date,to_date,d,i) AS(
  SELECT from_date,to_date,from_date AS d,1 AS i
  FROM test

  UNION ALL

  SELECT from_date,to_date,DATEADD(DAY,1,d),i+1
  FROM dateCTE
  WHERE d<to_date
)
SELECT d,i
FROM dateCTE

正确的结果

d           i
2017-11-01  1
2017-11-02  2
2017-11-03  3
2017-11-04  4
2017-11-05  5
2017-11-06  6
2017-11-07  7
2017-11-08  8
2017-11-09  9
2017-11-10  10
2017-11-11  11
2017-11-12  12
2017-11-13  13
2017-11-14  14
2017-11-15  15

为什么它在 Oracle 中不起作用?您可以建议哪些替代变体?谢谢!

真实系统的屏幕截图:

【问题讨论】:

  • 它在 Oracle 11g 中为我工作。你确定你的测试表中有正确的值吗?
  • @pablomatico - 是的,我确定。请参阅我的演示 SQL Fiddle - sqlfiddle.com/#!4/36907/5 我之前在真实系统上已经遇到过这个问题。
  • 您的确切 Oracle 版本是多少?
  • Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
  • 如果我没记错的话,这是在 11.2.0.3 或更高版本中修复的错误。 (无论如何,11.2.0.1 不再受支持。11.2.0.4 是唯一仍受支持的 11.2 版本)

标签: sql oracle common-table-expression


【解决方案1】:

如果你想有一个连续的从日期到现在,使用这样的选择:

SELECT  DATE '2017-11-01' + LEVEL - 1 AS D, LEVEL AS I
FROM DUAL
CONNECT BY LEVEL <= DATE '2017-11-15' - DATE '2017-11-01' + 1;

【讨论】:

  • 好老CONNECT BY。 ) 我认为它适用于任何 Oracle 版本。谢谢!
【解决方案2】:

它在 Oracle 11.2 Enterprise 中为我工作。但是,您的 SQL 小提琴清楚地表明它并非在每个 Oracle 版本中都存在。

我记得我在递归查询中遇到过类似的日期问题。所以有一个错误,已在较新版本中修复。很有可能,你的Oracle版本有这个bug。

解决方法:仅从递归查询中获取整数偏移量,然后将它们添加到 from_date:

WITH dateCTE(from_date, i, iend) AS
(
  SELECT from_date, 1 AS i, to_date - from_date as iend
  FROM test
  UNION ALL
  SELECT from_date, i + 1, iend
  FROM dateCTE
  WHERE i <= iend
)
, dates as (select i, from_date + i - 1 as d from dateCTE)
SELECT d, i
FROM dates;

【讨论】:

  • bug 编号为 11840579,已在 11.2.0.3 和 12.1.0.1 中修复
  • @a_horse_with_no_name - 谢谢!你能把它写成答案吗?我将结束我的问题。
  • 我认为由于解决方法,您的答案应该保留(并被接受)。
  • 好的。非常感谢你!我接受了CONNECT BY 声明的答案。
  • @Thorsten Kettner - 您的查询不适用于此 Oracle 版本 - ORA-00600: internal error code, arguments: [rworupo.1], [21], [8], [], [], [], [], [], [], [], [], []。谢谢你!
猜你喜欢
  • 2021-10-19
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
相关资源
最近更新 更多