CTEとSubQueryの違いは?


143

この投稿から次の手順でROW_NUMBERを使用するにはどうすればよいですか?

回答には2つのバージョンがあり、1つはa sub-queryを使用し、もう1つはa を使用しCTEて同じ問題を解決します。

さてCTE (Common Table Expression)、「サブクエリ」よりも使用することの利点は何ですか(したがって、クエリが実際に行っていることをより読みやすくします)

使用しての唯一の利点CTEを超えるにはsub-select、私が実際にできることである名前を付けますsub-queryCTEが単純な(再帰的でない)CTEとして使用される場合、これら2つの間に他の違いはありますか?


適切なディスカッションを伴う派生的な質問:stackoverflow.com/q/11169550/781695
user

7
IMO、CTEが読みにくいと考える人は誰でも、織り交ぜられたサブクエリの巨大な塊が、大部分のエンタープライズデータ管理システム全体で使用されている複雑な鋸歯状のクエリのガベージパイルを見たことがない。大規模で重要なクエリは、通常、サブクエリよりも後で、または新しい目で読む方が劇的に簡単です。少なくともPostgresの場合、多くの場合、魔法のようにはるかに優れたパフォーマンス発揮します。([理由はまだ理解していない[(stackoverflow.com/questions/33731068/…)、反対の可能性が高いため。)
zxq9

回答:


102

サブクエリと単純な(再帰的でない)CTEバージョンでは、おそらく非常によく似ています。プロファイラーと実際の実行計画を使用して違いを特定する必要がありますが、それはセットアップに固有です(そのため、完全な答えはわかりません)。

では一般 ; CTEは再帰的に使用できます。サブクエリはできません。これにより、ツリー構造に特に適しています。


1
申し訳ありませんが、私の質問をもっと明確にすべきでした。CTEとLIKEサブクエリが使用されるコンテキストで、CTEとサブクエリの違いは何ですか?
dance2die 2009

2
@Marc Gravell:プロファイラーの動作は保証されていないため、CTEの動作(評価の観点から)とは異なり、それ以上のことができます。
casperOne 2009

1
CTSとサブクエリの違いを見る人にとって、このステートメントがどれほど意味があるかわかりませんA CTE can be used recursively; a sub-query cannot。例は素晴らしいでしょう。
Aniket Thakur 2017

88

共通テーブル式の主な利点(再帰クエリで使用しない場合)はカプセル化です。サブクエリを使用するすべての場所で宣言する必要がなく、一度定義すれば複数の参照を持つことができます。それに。

ただし、これは1回だけ実行されることを意味するわけではありませこの非常に回答の以前の反復に従って、コメントしてくれたすべてに感謝します)。クエリは、複数回参照されると、複数回実行される可能性があります。クエリオプティマイザーは、最終的にCTEの解釈方法を決定します


「CTEを一時テーブル変数として考える」とは、CTEがディスクまたはメモリに格納されることを意味しますか?
dance2die 2009

定義により、CTEまたはサブクエリを複数のクエリで使用することはできません。オプティマイザーがCTEを処理するのと同じ方法でオプティマイザーがサブクエリを処理すると確信しています(1つのクエリ内で使用される回数に関係なく、結果セットを1回だけ評価します)
AlexCuse

@AlexCuse:私はCTEのコンテキストを十分に明確にしたと思いますが、より明確にするためにさらに追加しました。
casperOne 2009

@AlexCuse:CTEまたはサブクエリを複数の場所で使用できるという意味もありません。ただし、CTEとオプティマイザーの違いは、CTEの動作は保証されているのに対し、オプティマイザーの動作は保証されていないことです。
casperOne 2009

そして、オプティマイザがチョークし、サブクエリが2回以上評価されるいくつかのエッジケースが存在する可能性があることを認めますが、まだ実行していません。次に、できる限りCTEを使用します;)
AlexCuse

15

CTEは再帰に最も役立ちます。

WITH hier(cnt) AS (
        SELECT  1
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @n
        )
SELECT  cnt
FROM    hier

@n行を返します(最大101)。カレンダー、ダミー行セットなどに役立ちます。

また、(私の意見では)読みやすくなっています。

これとは別に、CTEsubqueriesは同一です。


MSSQLでは、WITHの前にセミコロン(;)を追加する必要があります。順序どおりに操作すると、エラーが発生します。それがあるべき;WITH blabla AS ...)
Obinna Nnenanya

2
@ObinnaNnenanya:バッチの最初のステートメントでない場合のみ。セミコロンを使用してステートメントを終了すると、SQL Serverが以前よりも、他の現在のバージョンでは、それを強制しませんが、とにかく良いアイデアであるWITHMERGEと同様の
Quassnoi

10

言及されていない1つの違いは、単一のCTEがユニオンのいくつかの部分で参照できることです


8

何か足りない場合を除き、CTEとサブクエリに同じように簡単に名前を付けることができます。

主な違いは読みやすさだと思います(CTEはサブクエリを途中で定義するのではなく、前もって定義するため、CTEの方が読みやすくなります)。

そして、再帰で何かをする必要がある場合、サブクエリでそれを行うには少し問題があります;)


1
美的でない違いがあるどうかはわかりません(特定の状況では、実行計画にわずかな違いがあると思います)。私を啓発する気?
AlexCuse、2010

2
CTEに名前を付けることができますが、エイリアスできるのはサブクエリのみです。違いは、複数のエイリアスを使用してCTEを再利用できることです(casperOneへのコメントでの@Michael Petitoの例を参照)。私はサブクエリでそれを行う方法を知りません。
kmote

7

誰も言及していない重要な事実の1つは、(少なくともpostgresでは)CTEが最適化のフェンスであることです。

https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/

つまり、クエリプラン全体に組み込まれるのではなく、独自のアトミッククエリとして扱われます。詳しい説明をする専門知識はありませんが、使用しているsqlのバージョンのセマンティクスを確認する必要があります。上級ユーザーの場合、クエリプランナーの制御のエキスパートレベルであれば、最適化フェンスを作成できるとパフォーマンスが向上します。ただし、99%のケースでは、クエリプランナーに何をすべきかを伝えようとしないでください。高速だと思うことは、高速だと思うよりも悪い可能性があります。:-)


6

他の回答に加えて、同じサブクエリを何度も使用している場合は、これらのすべてのサブクエリを1つのCTEに置き換えることができます。これにより、コードをより効果的に再利用できます。


4

理解しておく必要があることの1つは、古いバージョンのSQL Server(はいまだ多くの人がSQL Server 2000データベースをサポートする必要がある)では、CTEが許可されておらず、派生テーブルが最善のソリューションであることです。


2

ヒント:(MAXRECURSION n)

あなたは使用して特定の文に対して許可される再帰レベルの数を制限することができMAXRECURSIONヒントとの間で値032,767OPTION句を

たとえば、次のことを試すことができます。

OPTION 
      (MAXRECURSION 150)

GO
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.