我很难用语言来描述,所以这里是样本。
select *
into t
from (values (10, 'A'),
(25, 'B'),
(30, 'C'),
(45, 'D'),
(52, 'E'),
(61, 'F'),
(61, 'G'),
(61, 'H'),
(79, 'I'),
(82, 'J')
) v(userid, name)
注意F,G和H有相同的userid.
现在,考虑以下递归查询。
with tn as
(
select t.userId,t.name, row_number() over (order by userid,newid()) as seqnum
from t
),
cte as
(
select userId, name, seqnum as seqnum
from tn
where seqnum = 1
union all
select tn.userId, tn.name,tn.seqnum
from
cte
inner join tn on tn.seqnum = cte.seqnum + 1
)
select *
from cte
第一个cte,tn
,创建一个包含随机化组件的row_number,它将导致FGH以随机顺序出现。然而,它们仍然会各自出现一次(可以通过修改最后一个和最外层的行号来检查)。from
将要 from tn
)
第二节: cte
递归扫描 tn
. 里面没有什么太复杂的东西,因为它来自于一个最小化的例子。然而,很明显,锚构件被手动设置成了 tn
的第一行,然后递归扫描其余所有行。
然而,最终的结果集并不是每行都出现一次FGH!它们总共出现了3行,但可以任意组合。它们总共出现在3行中,但可以任意组合。FGH是可能的,但FFH也是可能的,甚至FFF也是可能的! 这是一个FHH的例子。
+--------+------+--------+
| userId | name | seqnum |
+--------+------+--------+
| 10 | A | 1 |
| 25 | B | 2 |
| 30 | C | 3 |
| 45 | D | 4 |
| 52 | E | 5 |
| 61 | F | 6 |
| 61 | H | 7 |
| 61 | H | 8 |
| 79 | I | 9 |
| 82 | J | 10 |
+--------+------+--------+
为什么会这样?
我想不是这样的 Ctes内的分析函数行为 有什么关系,因为 tn
其中包含的row_number不是递归的。
郑重声明,我得到这个问题是由于以下一系列的事件:有人问到 问号 的答案是 贤臣.同一个OP问 追问,我以为只要在原件上做一点手脚就能回答。但是,经过一番研究,我发现了一个我无法理解的行为。我尽可能的把例子做的最小化。
CTE的并不是spooled。 每次提到 tn
可能会导致重新运行查询并重新随机化结果。
为了避免这种情况,运行一次随机化查询并加载一个临时表。
select t.userId,t.name, row_number() over (order by userid,newid()) as seqnum
into #tn
from t
并在随后的查询中引用
with tn as
(
select * from #tn
),
cte as
(
select userId, name, seqnum as seqnum
from tn
where seqnum = 1
union all
select tn.userId, tn.name,tn.seqnum
from
cte
inner join tn on tn.seqnum = cte.seqnum + 1
)
select *
from cte