私はボスマンと話していましたが、彼はCTEよりもサブクエリを好みます。個人的に、私はサブクエリを嫌います。彼はサブクエリの方が速くなる可能性があると述べましたが、私は確信していません。私はこの短いテストを実行しました:
with classes as
(select top 10 Classkey from dimclass
group by classkey
order by count(1) desc),
policies as (
select CarrierKey, policykey, periodeffectivedate from dimpolicy),
exposure as (
select policykey, classkey from DimExposure)
select * from policies p
inner join exposure x on p.PolicyKey = x.PolicyKey
inner join classes c on x.ClassKey = c.Classkey
の実行計画があります:
https://www.brentozar.com/pastetheplan/?id=SJYJUZNHS
select p.CarrierKey, p.PolicyKey, p.periodeffectivedate from dimpolicy p
inner join (select policykey, classkey from DimExposure) x on p.PolicyKey = x.PolicyKey
inner join (select top 10 Classkey from dimclass
group by classkey
order by count(1) desc) c on x.ClassKey = c.Classkey
同じ実行プランがあります:
https://www.brentozar.com/pastetheplan/?id=rJs_LbVSr
質問:これは常に当てはまりますか? SQL Serverの奇妙で素晴らしい世界では、答えは常にに依存するようです。
現状のままでは、質問には答えられないと主張します。ネガを証明することは不可能であり、製品ドキュメントで保証が見つかりません。 2つのアプローチの技術的な違いの例が必要な場合は、Paul Whiteの Query Optimizer Deep Dive セッションの数分をご覧ください。誰かがそれをパフォーマンスのベストプラクティスにどのように変換できるかは明らかではありません。
パフォーマンスのベストプラクティスを見つけるのではなく、コーディングスタイルの問題として問題に取り組むことをお勧めします。派生テーブルのCTEまたはCTEの派生テーブルを切り替えることは、クエリを書き換える意味のある方法ではありません。
一般に、状況によって異なります。 CTEが派生テーブルより優れているケースの1つは、クエリでCTEを複数回参照する必要がある場合です。ばかげた例:
SELECT x,y
FROM (
SELECT x,y FROM T WHERE p
) AS A
WHERE x = (SELECT MAX(x) FROM T WHERE p)
対
WITH CTE (x,y) as (
SELECT x,y FROM T WHERE p
)
SELECT x,y FROM CTE WHERE x = (SELECT MAX(x) FROM CTE)
異なるデータベースエンジンは、CTEへの複数の参照を異なる方法で処理します。 SQL Serverでは、CTEは通常、参照ごとに完全に評価されます。