oracle递归循环日期,ORACLE(11.2.0.1.0) - 带有日期表达式的递归CTE(ORACLE (11.2.0.1.0) - Recursive CTE with a date expr...

ORACLE(11.2.0.1.0) - 带有日期表达式的递归CTE(ORACLE (11.2.0.1.0) - Recursive CTE with a date expression)

关于以下问题的正确答案:

如果我没记错的话,这是在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

)

SELECT d,i

FROM dateCTE

为了测试,我将条件改为i<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

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中返回了错误的结果?

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

)

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中不起作用? 您可以建议哪些替代变体? 谢谢!

来自真实系统的屏幕截图:

G5emX.png

qjiRp.png

VYfr0.png

The right answer on the following question:

That is a bug that was fixed in 11.2.0.3 or later if I recall correctly. (11.2.0.1 is no longer supported anyway. 11.2.0.4 is the only 11.2 release that is still supported) – @a_horse_with_no_name

The bug number is 11840579 and it was fixed in 11.2.0.3 and 12.1.0.1 – @a_horse_with_no_name

Question

I have a table

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'));

The following query in Oracle return only one row (expected 15 rows)

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

)

SELECT d,i

FROM dateCTE

For test I changed the condition to i<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

WHERE i<10 -- exit condition

)

SELECT d,i

FROM dateCTE

And get the next result

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

Why do this recursive query returned bad result in Oracle?

I ran a similar query in SQLServer and I get the right result

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

)

SELECT d,i

FROM dateCTE

The right result

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

Why it doesn't work in Oracle? What alternative variants can you suggest? Thank you!

Screen shots from a real system:

G5emX.png

qjiRp.png

VYfr0.png

原文:https://stackoverflow.com/questions/47526482

更新时间:2019-12-12 22:20

最满意答案

如果您想拥有从日期到最新的顺序,请使用以下选项:

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;

If you want to have a sequential from-date to to-date, Use such this select:

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;

2017-11-28

相关问答

这里你不需要一个“真正的”递归CTE。 您可以使用一个月份参考: ;WITH Months

as

(

SELECT DATEADD(day, -DATEPART(day, GETDATE())+1, GETDATE()) as 'MonthStart'

UNION ALL

SELECT DATEADD(month, -1, MonthStart) as 'MonthStart'

FROM Months

)

然后你可以在上面的查询中JOIN SELECT TOP 1

...

在子查询vs 简单 (非递归)CTE版本中,它们可能非常相似。 您将不得不使用分析器和实际执行计划来发现任何差异,这将与您的设置特定(因此我们无法全面告诉您答案)。 一般来说 CTE可以递归使用; 一个子查询不行。 这使得它们特别适合于树结构。 In the sub-query vs simple (non-recursive) CTE versions, they are probably very similar. You would have to use the profiler and

...

如果您想拥有从日期到最新的顺序,请使用以下选项: 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;

If you want to have a sequential from-date to to-date, Use such this select: SELECT DATE '2017-1

...

您是否需要输出每个组或者是否足以知道点值? 如果是后者,你可以把它看作是“差距和岛屿”问题的变种。 如果你想深入了解, 这里有一篇很好的文章。 我正在调整该页面中的一个代码段。 将起点定义为在记录之前3天内没有记录的记录。 终点是在3天之内没有记录的记录。 一旦识别出每个岛屿,我们就可以获取起点和终点之间的天数,并通过将答案分开并舍入来确定其中有多少3天组合。 注意:以下代码是针对组织1的硬编码。 CREATE TABLE #t(

OrganizationMrn int,

Visi

...

我已经做出了一些假设,你的描述没有像书面描述的那样完全有意义,但是下面的结果会达到你想要的结果: if object_id('tempdb.dbo.#leads', 'u') is not null

drop table #leads;

create table #leads (lead_id int, customer_id int, lead_created_date datetime, salesperson_name varchar(20))

insert into #leads

val

...

只需在开始时recursive ,即使递归递归到后来: with recursive cte1 as (

...

), cte2 as (

-- here comes the recursive cte

...

)

select *

from ...

Just put the recursive at the start, even if the recursive one comes later: with recursive cte1 as (

...

), cte2 as (

...

where B.Name in ('BCD')是将结果集过滤到一行的内容。 将其更改为以下,您应该得到您想要的结果: ;with cte (Name, GUID, ParentGUID)

as

(

select distinct B.Name

,B.GUID

,B.ParentGUID

from EMP B

where B.Name in ('BCD')

union All

...

好的,我决定将xa-datasource-class放在standalone.xml中的上

oracle.jdbc.driver.OracleDriver

OK I resolved with putting xa-datasource-class on <

...

创建一个TVF: CREATE FUNCTION my_function (

@ProviderId int

)

RETURNS @ProviderTable TABLE

(

Id int NULL,

ProviderId int NULL,

ConsumerId int NULL

)

AS

BEGIN

WITH cte AS (

SELECT Id,

ProviderId,

...

WITH子句用于SELECT语句。 从文档: “您可以在任何顶级SELECT语句和大多数类型的子查询中指定此子句。” (强调我的)。 如果您真的需要这样做,可以使用ORAFAQ来解决这个问题。 主要的博客文章就在这里。 The WITH clause is for use with a SELECT statement. From the documents: "You can specify this clause in any top-level SELECT statement and in

...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值