SQL es un lenguaje declarativo, no un lenguaje procedimental. Es decir, construye una instrucción SQL para describir los resultados que desea. No le está diciendo al motor SQL cómo para hacer el trabajo.
Como regla general, es una buena idea dejar que el motor de SQL y el optimizador de SQL encuentren el mejor plan de consulta. Se requieren muchos años-persona de esfuerzo para desarrollar un motor SQL, así que deje que los ingenieros hagan lo que saben hacer.
Por supuesto, hay situaciones en las que el plan de consulta no es óptimo. Luego, desea usar sugerencias de consulta, reestructurar la consulta, actualizar estadísticas, usar tablas temporales, agregar índices, etc. para obtener un mejor rendimiento.
En cuanto a tu pregunta. El rendimiento de las CTE y las subconsultas debería, en teoría, ser el mismo, ya que ambos proporcionan la misma información al optimizador de consultas. Una diferencia es que un CTE utilizado más de una vez podría identificarse y calcularse fácilmente una vez. Los resultados podrían almacenarse y leerse varias veces. Desafortunadamente, SQL Server no parece aprovechar este método básico de optimización (podría llamar a esta eliminación de subconsulta común).
Las tablas temporales son un asunto diferente, porque proporciona más orientación sobre cómo se debe ejecutar la consulta. Una diferencia importante es que el optimizador puede usar estadísticas de la tabla temporal para establecer su plan de consulta. Esto puede resultar en ganancias de rendimiento. Además, si tiene una CTE (subconsulta) complicada que se usa más de una vez, almacenarla en una tabla temporal a menudo mejorará el rendimiento. La consulta se ejecuta solo una vez.
La respuesta a su pregunta es que necesita experimentar para obtener el rendimiento que espera, especialmente para consultas complejas que se ejecutan de forma regular. En un mundo ideal, el optimizador de consultas encontraría la ruta de ejecución perfecta. Aunque a menudo lo hace, es posible que pueda encontrar una manera de obtener un mejor rendimiento.