Мне трудно использовать слова, чтобы описать это, поэтому вот образец:
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 имеют один и тот же идентификатор пользователя.
Теперь рассмотрим следующий рекурсивный запрос:
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, который включает в себя компонент рандомизации, который заставит F/G/H появляться в случайном порядке. Однако все они по-прежнему будут появляться по одному разу (это легко проверить, изменив последний и самый внешний from
на from tn
)
Второй cte, cte
, рекурсивно сканирует tn
. В этом нет ничего слишком сложного, потому что он исходит из свернутого примера. Однако очевидно, что элемент привязки вручную устанавливается как первая строка tn
, а затем рекурсия сканирует все остальные строки.
Однако в окончательном наборе результатов F/G/H не появляются по одному разу! Все они появляются в 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, не является рекурсивным.
Для протокола, я получил этот вопрос из-за следующей последовательности событий: кто-то спросил вопрос, на который отлично ответил участник. Тот же ОП задал дополнительный вопрос, на что я мог бы ответить, немного подделав оригинал. Однако, немного покопавшись, я обнаружил поведение, которое не могу понять. Я сделал пример максимально минимальным.