Разница между CTE и SubQuery?

Из этого поста Как использовать ROW_NUMBER в следующей процедуре?

Существуют две версии ответов, в которых один использует SubQuery а другой использует CTE для решения той же проблемы.

Теперь, что является преимуществом использования CTE (Common Table Expression) сравнению с ub-query (таким образом, более читабельно, что на самом деле делает запрос)

Единственное преимущество использования CTE перед подвыбором - это то, что я могу назвать подзапрос. Есть ли другие различия между этими двумя, когда CTE используется как простой (не рекурсивный) CTE?

Ответ 1

В подзапросах с простыми (нерекурсивными) версиями CTE они, вероятно, очень похожи. Вам нужно будет использовать профилировщик и фактический план выполнения, чтобы выявить любые различия, и это будет специфично для вашей установки (поэтому мы не можем полностью ответить на ваш ответ).

В общем; CTE может использоваться рекурсивно; подзапрос не может. Это делает их особенно хорошо подходящими для древовидных структур.

Ответ 2

Основным преимуществом Common Table Expression (когда он не используется для рекурсивных запросов) является инкапсуляция, вместо того, чтобы объявлять подзапрос в каждом месте, где вы хотите его использовать, вы можете определить его один раз, но иметь несколько ссылок к этому.

Однако это не означает, что он выполняется только один раз (согласно предыдущим итерациям этого самого ответа, спасибо всем, кто прокомментировал). Запрос определенно может быть выполнен несколько раз, если на него ссылаются несколько раз; Оптимизатор запросов в конечном итоге принимает решение о том, как следует интерпретировать CTE.

Ответ 3

CTE наиболее полезны для рекурсии:

WITH hier(cnt) AS (
        SELECT  1
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @n
        )
SELECT  cnt
FROM    hier

вернет строки @n (до 101). Полезно для календарей, фиктивных наборов строк и т.д.

Они также более читабельны (на мой взгляд).

Кроме того, CTE и subqueries идентичны.

Ответ 4

Одно отличие, о котором не упоминалось, - это один CTE, на который можно ссылаться в нескольких частях объединения

Ответ 5

Если я что-то не хватает, вы можете назвать CTE и подзапросы так же легко.

Я предполагаю, что основное отличие - читаемость (я нахожу CTE более читаемым, потому что он определяет ваш подзапрос спереди, а не посередине).

И если вам нужно что-то сделать с рекурсией, у вас будет небольшая проблема с подзапросом;)

Ответ 6

Добавляя ответы других, если вы используете один и тот же подзапрос, который используется несколько раз, вы можете заменить все эти подзапросы одним CTE. Это позволяет вам лучше использовать код.

Ответ 7

Один важный факт, который никто не упомянул, заключается в том, что (по крайней мере, в postgres) CTE являются заборами оптимизации:

https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/

То есть они будут рассматриваться как их собственный атомарный запрос, а не как весь план запроса. Мне не хватает опыта, чтобы дать лучшее объяснение, но вы должны проверить семантику для версии SQL, которую вы используете; для опытных пользователей возможность создать забор оптимизации может повысить производительность, если вы являетесь экспертом в управлении планировщиком запросов; однако в 99% случаев вам следует избегать попыток указать планировщику запросов, что делать, потому что то, что вы думаете, будет быстрее, вероятно, хуже, чем то, что, по его мнению, будет быстрее. :-)

Ответ 8

Одной вещью, которую необходимо понять, также является то, что в более старых версиях SQL Server (да, многие люди все еще должны поддерживать базы данных SQL Server 2000), CTE не разрешены, а затем производная таблица является вашим лучшим решением.

Ответ 9

СОВЕТ: (МАКСИРОВАНИЕ n)

вы можете ограничить количество уровней рекурсии, разрешенных для определенного с помощью подсказки MAXRECURSION и значения между 0 и 32 767 в предложении OPTION

Например, вы можете попробовать:

OPTION 
      (MAXRECURSION 150)

GO