ROW_NUMBER 在 CTE 中不起作用
ROW_NUMBER is not working in CTE
我正在研究报告,似乎 row_number 在递归中不起作用。
!!我已经简化了示例!
来自 table,有 3 条记录:
declare @sometable table (id int, id2 int)
insert into @sometable
select 1 as id, 11 as id2
union all
select 2, 22
union all
select 3, 33
在 CTE 中 select 全部并标记要在下一次迭代中排除的第一条记录:
;with cte(iteration, ord, id, id2, deal) as
(
select ordered.*
, deal = (case when ord = 1 then 1 else 0 end)
from
(select 1 iteration,
ord = ROW_NUMBER() OVER (ORDER BY id),
st.*
FROM @sometable st) ordered
)
select * from CTE
union all
select
ordersinverted.nextIteration,
ordersinverted.ord,
ordersinverted.id,
ordersinverted.id2,
deal = (case when ord = 1 then 1 else 0 end)
from (
select
ROW_NUMBER() OVER (PARTITION BY ord ORDER BY iteration desc) as reversedIteration,
ROW_NUMBER() OVER (ORDER BY cte.id) as ord,
iteration + 1 as nextIteration,
cte.id,
cte.id2
from cte
where cte.deal = 0
) ordersinverted
它给了我 3 次迭代的预期结果:
使用 row_number out of CTE result
我非常希望得到类似的结果并递归调用select。不幸的是,这是怀疑存在错误的地方:
;with cte(iteration, ord, id, id2, deal) as
(
select ordered.*
, deal = (case when ord = 1 then 1 else 0 end)
from
(select 1 iteration,
ord = ROW_NUMBER() OVER (ORDER BY id),
st.*
FROM @sometable st) ordered
union all
select
ordersinverted.nextIteration,
ordersinverted.ord,
ordersinverted.id,
ordersinverted.id2,
deal = (case when ord = 1 then 1 else 0 end)
from (
select
ROW_NUMBER() OVER (PARTITION BY ord ORDER BY iteration desc) as reversedIteration,
ROW_NUMBER() OVER (ORDER BY cte.id) as ord,
iteration + 1 as nextIteration,
cte.id,
cte.id2
from cte
where cte.deal = 0
) ordersinverted
)
select * from CTE
使用row_numberwithin CTE result
哦,对不起。这必须有一个问题格式:
所以我的问题是:这是功能还是错误?
请注意,对 Oracle 的类似查询将按预期工作:
with T (id,grp_id) as (
select 1 as id,1 as grp_id from dual union all
select 2 as id,1 as grp_id from dual union all
select 3 as id,1 as grp_id from dual union all
select 1 as id,2 as grp_id from dual union all
select 2 as id,2 as grp_id from dual union all
select 3 as id,2 as grp_id from dual )
,
rec (id,grp_id,rn) as (
select id, grp_id, row_number()over(partition by grp_id order by id) rn from T where grp_id=1
union all
select t.id, t.grp_id, row_number() over(partition by t.grp_id order by t.id) rn from T inner join rec on t.id=rec.id and t.grp_id=rec.grp_id+1
)
PS。如果使用 max() 或 min() 函数,它的工作方式类似...
这是记录在案的行为。因此,它应该被视为 "feature"。这是此案例的文档:https://msdn.microsoft.com/en-us/library/ms175972.aspx
Analytic and aggregate functions in the recursive part of the CTE are
applied to the set for the current recursion level and not to the set
for the CTE. Functions like ROW_NUMBER operate only on the subset of
data passed to them by the current recursion level and not the entire
set of data passed to the recursive part of the CTE. For more
information, see example K. Using analytical functions in a recursive
CTE that follows.
本文的第 K 段有一个很好的演示,演示了 ROW_NUMBER 函数在递归 CTE 中的行为。因为递归CTE是逐行处理数据,所以CTE递归部分的ROW_NUMBER永远是return 1,可以把ROW_NUMBER() OVER (ORDER BY id)
改成COUNT(*) OVER ()
,看看有多少行 SQL 服务器进程同时用于锚点和 CTE 的递归部分。分别会有3个和1个
我正在研究报告,似乎 row_number 在递归中不起作用。
!!我已经简化了示例!
来自 table,有 3 条记录:
declare @sometable table (id int, id2 int)
insert into @sometable
select 1 as id, 11 as id2
union all
select 2, 22
union all
select 3, 33
在 CTE 中 select 全部并标记要在下一次迭代中排除的第一条记录:
;with cte(iteration, ord, id, id2, deal) as
(
select ordered.*
, deal = (case when ord = 1 then 1 else 0 end)
from
(select 1 iteration,
ord = ROW_NUMBER() OVER (ORDER BY id),
st.*
FROM @sometable st) ordered
)
select * from CTE
union all
select
ordersinverted.nextIteration,
ordersinverted.ord,
ordersinverted.id,
ordersinverted.id2,
deal = (case when ord = 1 then 1 else 0 end)
from (
select
ROW_NUMBER() OVER (PARTITION BY ord ORDER BY iteration desc) as reversedIteration,
ROW_NUMBER() OVER (ORDER BY cte.id) as ord,
iteration + 1 as nextIteration,
cte.id,
cte.id2
from cte
where cte.deal = 0
) ordersinverted
它给了我 3 次迭代的预期结果: 使用 row_number out of CTE result
我非常希望得到类似的结果并递归调用select。不幸的是,这是怀疑存在错误的地方:
;with cte(iteration, ord, id, id2, deal) as
(
select ordered.*
, deal = (case when ord = 1 then 1 else 0 end)
from
(select 1 iteration,
ord = ROW_NUMBER() OVER (ORDER BY id),
st.*
FROM @sometable st) ordered
union all
select
ordersinverted.nextIteration,
ordersinverted.ord,
ordersinverted.id,
ordersinverted.id2,
deal = (case when ord = 1 then 1 else 0 end)
from (
select
ROW_NUMBER() OVER (PARTITION BY ord ORDER BY iteration desc) as reversedIteration,
ROW_NUMBER() OVER (ORDER BY cte.id) as ord,
iteration + 1 as nextIteration,
cte.id,
cte.id2
from cte
where cte.deal = 0
) ordersinverted
)
select * from CTE
使用row_numberwithin CTE result
哦,对不起。这必须有一个问题格式: 所以我的问题是:这是功能还是错误?
请注意,对 Oracle 的类似查询将按预期工作:
with T (id,grp_id) as (
select 1 as id,1 as grp_id from dual union all
select 2 as id,1 as grp_id from dual union all
select 3 as id,1 as grp_id from dual union all
select 1 as id,2 as grp_id from dual union all
select 2 as id,2 as grp_id from dual union all
select 3 as id,2 as grp_id from dual )
,
rec (id,grp_id,rn) as (
select id, grp_id, row_number()over(partition by grp_id order by id) rn from T where grp_id=1
union all
select t.id, t.grp_id, row_number() over(partition by t.grp_id order by t.id) rn from T inner join rec on t.id=rec.id and t.grp_id=rec.grp_id+1
)
PS。如果使用 max() 或 min() 函数,它的工作方式类似...
这是记录在案的行为。因此,它应该被视为 "feature"。这是此案例的文档:https://msdn.microsoft.com/en-us/library/ms175972.aspx
Analytic and aggregate functions in the recursive part of the CTE are applied to the set for the current recursion level and not to the set for the CTE. Functions like ROW_NUMBER operate only on the subset of data passed to them by the current recursion level and not the entire set of data passed to the recursive part of the CTE. For more information, see example K. Using analytical functions in a recursive CTE that follows.
本文的第 K 段有一个很好的演示,演示了 ROW_NUMBER 函数在递归 CTE 中的行为。因为递归CTE是逐行处理数据,所以CTE递归部分的ROW_NUMBER永远是return 1,可以把ROW_NUMBER() OVER (ORDER BY id)
改成COUNT(*) OVER ()
,看看有多少行 SQL 服务器进程同时用于锚点和 CTE 的递归部分。分别会有3个和1个