Zu bedenken ist nur, dass eine CTE keine wirkliche temporäre Tabelle ist.
Je nach Lust des Optimizers wird für Join, Subselects o.ä. eine *QUERYnnn verwendet oder eben auch nicht (meistens).
CTE vereinfacht nur die Schreibweise und die Wiederverwendung:

with cte1 as (select k1, f1 from tab1)
, cte2 as (select k2, sum(f2) f2 from tab2 Group by k2)
select * from cte1
inner join cte2 on k1=k2

ist identisch zu

select * from (select k1, f1 from tab1) cte1
inner join (select k2, sum(f2) from tab2) cte2 on k1=k2

Der Vorteil der CTE ist die übersichtlichere Schreibweise und eben die Wiederverwendung wenn ich eine Tabelle mehr als 1 Mal joine.
Zur Laufzeit wird dann aber auch der CTE-Ausdruck n Mal ausgeführt. Ggf. also auch n *QUERYnnn-Tabellen.