SQL é uma linguagem declarativa, não uma linguagem processual. Ou seja, você constrói uma instrução SQL para descrever os resultados que deseja. Você não está dizendo ao mecanismo SQL como fazer o trabalho.
Como regra geral, é uma boa ideia deixar o mecanismo e o otimizador de SQL encontrar o melhor plano de consulta. Há muitos anos-pessoa dedicados ao desenvolvimento de um mecanismo SQL, portanto, deixe os engenheiros fazerem o que sabem fazer.
Obviamente, há situações em que o plano de consulta não é ideal. Então você deseja usar dicas de consulta, reestruturar a consulta, atualizar estatísticas, usar tabelas temporárias, adicionar índices e assim por diante para obter melhor desempenho.
Quanto à sua pergunta. O desempenho de CTEs e subconsultas deve, em teoria, ser o mesmo, pois ambos fornecem as mesmas informações para o otimizador de consultas. Uma diferença é que uma CTE usada mais de uma vez pode ser facilmente identificada e calculada uma vez. Os resultados podem ser armazenados e lidos várias vezes. Infelizmente, o SQL Server não parece tirar proveito desse método básico de otimização (você pode chamar essa eliminação de subconsulta comum).
As tabelas temporárias são uma questão diferente, porque você fornece mais orientações sobre como a consulta deve ser executada. Uma grande diferença é que o otimizador pode usar estatísticas da tabela temporária para estabelecer seu plano de consulta. Isso pode resultar em ganhos de desempenho. Além disso, se você tiver uma CTE (subconsulta) complicada usada mais de uma vez, armazená-la em uma tabela temporária geralmente oferecerá um aumento no desempenho. A consulta é executada apenas uma vez.
A resposta para sua pergunta é que você precisa brincar para obter o desempenho esperado, principalmente para consultas complexas que são executadas regularmente. Em um mundo ideal, o otimizador de consultas encontraria o caminho de execução perfeito. Embora isso aconteça com frequência, você poderá encontrar uma maneira de obter melhor desempenho.