Аналитические функции отличаются тем, что для их решения требуется известный набор результатов.Они зависят от следующего, предшествующего или полного набора результатов для расчета текущего значения.Тем не менее, представление слияния никогда не допускается в представлении, которое содержит аналитическую функцию.Зачем?Это изменит результат.
Пример:
Select * from (
select row_number() over (partition by c1 order by c2) rw, c3 from t) z
where c3=123
- это не то же самое, что
select row_number() over (partition by c1 order by c2) rw, c3 from t
where c3=123
. Эти 2 будут возвращать различные значения для rw.Вот почему подзапросы, содержащие аналитические функции, всегда будут полностью разрешены ранее и никогда не будут объединены с остальными.
Обновление
Просмотр 2-го запроса:
WITH myCTE
AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY Score desc) AS RowNumber, 1 AS RecurseLevel
FROM tblGroups
WHERE ParentId IS NULL
)
SELECT tblGroups.*,
ROW_NUMBER() OVER (ORDER BY myCTE.RowNumber , tblGroups.Score desc) AS RowNumber,
RecurseLevel + 1 AS RecurseLevel
FROM tblGroups
JOIN myCTE
ON myCTE.GroupID = tblGroups.ParentID;
Он работает точно так же, как если бы он был написан следующим образом (Тот же план выполнения и результат):
SELECT tblGroups.*,
ROW_NUMBER() OVER (ORDER BY myCTE.RowNumber , tblGroups.Score desc) AS RowNumber,
RecurseLevel + 1 AS RecurseLevel
FROM tblGroups
JOIN (
SELECT *, ROW_NUMBER() OVER (ORDER BY Score desc) AS RowNumber, 1 AS RecurseLevel
FROM tblGroups
WHERE ParentId IS NULL
)myCTE ON myCTE.GroupID = tblGroups.ParentID;
Этот код необходимо разбить на части, чтобы сбросить число.
Рекурсивнозапросы не работают в цикле while, они не являются процедурными.По сути, они работают как рекурсивная функция, но в зависимости от таблиц, запросов, индексов их можно оптимизировать для выполнения в ту или иную сторону.
Если мы действительно придерживаемся концепции, что представление не можетбыть объединенным при использовании аналитических функций и просмотре запроса 1. Он может выполняться только один раз, и он находится во вложенном цикле.
WITH myCTE
AS
( /*Cannot be merged*/
SELECT *, ROW_NUMBER() OVER (ORDER BY Score desc) AS RowNumber, 1 AS RecurseLevel,
cast(0 as bigint) n
FROM tblGroups
WHERE ParentId IS NULL
UNION ALL
/*Cannot be merged*/
SELECT tblGroups.*,
ROW_NUMBER() OVER (ORDER BY myCTE.RowNumber, tblGroups.Score desc) AS RowNumber, RecurseLevel + 1 AS RecurseLevel,
myCTE.RowNumber
FROM tblGroups
JOIN myCTE
ON myCTE.GroupID = tblGroups.ParentID
)
SELECT *
FROM myCTE;
Так что 1-й выбор не может быть объединен 2-й, ни один.Единственный способ выполнить этот запрос - это вложенный цикл для каждого элемента, возвращаемого на каждом уровне, следовательно, сброс.Опять же, это не вопрос процедурного или нет, просто вопрос возможного плана выполнения.
Надеюсь, что это ответ на ваш вопрос, позвольте мне, если это не так:)
y