SQL является декларативным языком, а не процедурным языком. То есть вы создаете оператор SQL для описания желаемых результатов. Вы не говорите движку SQL, как выполнять работу.
Как правило, желательно, чтобы механизм SQL и оптимизатор SQL нашли лучший план запроса. На разработку движка SQL уходит много человеко-лет, поэтому позвольте инженерам делать то, что они умеют.
Конечно, бывают ситуации, когда план запроса не является оптимальным. Затем вы хотите использовать подсказки запроса, реструктурировать запрос, обновлять статистику, использовать временные таблицы, добавлять индексы и т. Д., Чтобы повысить производительность.
Что касается вашего вопроса. Теоретически производительность CTE и подзапросов должна быть одинаковой, поскольку оба предоставляют одинаковую информацию оптимизатору запросов. Одно из отличий состоит в том, что CTE, использованный более одного раза, может быть легко идентифицирован и рассчитан один раз. Результаты могут быть сохранены и прочитаны несколько раз. К сожалению, SQL Server, похоже, не использует преимущества этого базового метода оптимизации (вы можете назвать это общим устранением подзапроса).
Временные таблицы - это другое дело, потому что вы предоставляете больше рекомендаций о том, как должен выполняться запрос. Одно из основных отличий заключается в том, что оптимизатор может использовать статистику из временной таблицы для составления плана запроса. Это может привести к повышению производительности. Кроме того, если у вас есть сложный CTE (подзапрос), который используется более одного раза, то сохранение его во временной таблице часто дает повышение производительности. Запрос выполняется только один раз.
Ответ на ваш вопрос заключается в том, что вам нужно поиграть, чтобы получить ожидаемую производительность, особенно для сложных запросов, которые выполняются на регулярной основе. В идеальном мире оптимизатор запросов нашел бы идеальный путь выполнения. Хотя это часто бывает, вы можете найти способ повысить производительность.