Разница между CTE и SubQuery? - PullRequest
127 голосов
/ 01 апреля 2009

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

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

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

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

Ответы [ 9 ]

88 голосов
/ 01 апреля 2009

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

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

77 голосов
/ 01 апреля 2009

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

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

15 голосов
/ 01 апреля 2009

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 идентичны.

10 голосов
/ 19 февраля 2012

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

8 голосов
/ 01 апреля 2009

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

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

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

7 голосов
/ 04 августа 2017

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

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

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

6 голосов
/ 24 сентября 2009

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

4 голосов
/ 26 января 2011

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

2 голосов
/ 31 марта 2015

ПОДСКАЗКА: (МАКСРЕКУРСИЯ n)

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

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

OPTION 
      (MAXRECURSION 150)

GO
...