具有排名函数的递归 cte
如何在递归cte中使用排名函数? 这是一个简单的例子,展示了我正在尝试做的事情:
with cte as ( select 1 a, 1 b union all select 1, 2 union all select 2, 3 union all select 2, 4 ) , rcte (a, b, c, d) as ( select a, b, cast(0 as int), 1 from cte union all select a, b, cast(ROW_NUMBER() over (partition by a order by b) as int), d+1 from rcte where d < 2 ) select * from rcte where d=2 order by a, b
为什么没有排名?请告诉我我的错误
How to use ranking functions in recursive cte?
Here's simple example showing how I'm trying to do:
with cte as ( select 1 a, 1 b union all select 1, 2 union all select 2, 3 union all select 2, 4 ) , rcte (a, b, c, d) as ( select a, b, cast(0 as int), 1 from cte union all select a, b, cast(ROW_NUMBER() over (partition by a order by b) as int), d+1 from rcte where d < 2 ) select * from rcte where d=2 order by a, b
Why there's no ranking? Show me my mistake pls
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑
当您阅读有关递归的 CTE 文档时,您会注意到它有一些限制,例如无法使用子查询、group-by、top。这些都涉及多行。通过有限的测试、检查执行计划以及测试这个查询,
我只能得出结论:
虽然我很容易得出这个结论,但有人显然花了更多的时间以令人难以忍受的细节进行解释 仅 17 个月前...
换句话说,这是SQL Server 实现递归 CTE 的本质,因此窗口函数不会按您期望的方式工作。
For the benefit of others, the output is:
而您期望 c 包含 1,2,1,2 而不是 1,1,1,1。
这看起来确实可能是一个错误,因为没有文档表明窗口函数不应在 CTE 的递归部分中工作。注意:row_number() 返回bigint,因此您可以仅将anchor(c) 转换为bigint。
由于每次迭代都会增加 d,因此您可以在外部执行窗口化。
编辑-洞察力
同时回答另一个问题< super>link,我又玩了一些递归 CTE。如果您在没有最终 ORDER BY 的情况下运行它,您可以看到 SQL Server 如何接近递归。有趣的是,在这种情况下它会向后退,然后对每一行进行完整的深度优先递归。
示例表
递归查询
输出显示在迭代第一次中处理的 CTE 锚点,然后由于某种原因锚集中的每一行在处理其他行之前都会递归完成(深度优先)。
但它确实有其奇怪的用途,如这个答案显示
EDIT
When you read the CTE documentation regarding recursion, you will notice that it has some limits, such as not being able to use subqueries, group-by, top. These all involve multiple rows. From limited testing, and checking the execution plan, as well as testing this query
I can only conclude:
Although I came to this conclusion easily, someone obviously took a lot more time to explain it in excruciating detail only 17 months ago...
In other words, this is the nature of SQL Server's implementation of the recursive CTE, so windowing functions will not work the way you expect it to.
For the benefit of others, the output is:
Whereas you are expecting c to contain 1,2,1,2 instead of 1,1,1,1.
This certainly seems like it could be a bug, since there is no documentation to say that windowing functions should not work in the recursive part of a CTE.Note: row_number() returns bigint, so you can cast just the anchor(c) as bigint.
Since each iteration increases d, you could perform the windowing outside.
EDIT - insight
While answering another questionlink, I played some more with recursive CTE. If you run it without the final ORDER BY, you can see how SQL Server is approaching the recursion. It is interesting that it goes backwards in this case, then does a full depth-first recursion on each row.
Sample table
A recursive query
The output shows the CTE anchor processed in iteration one, then for whatever reason each row in the anchor set is recursed to completion (depth-first) before processing other rows.
Yet it does have its strange uses, as this answer shows