2011-07-25 6 views
7

Oracle、DB2、SybaseのすべてのRDBMSがサブクエリの共通テーブル式(CTE)をサポートしていることを理解する助けが必要です。私は、PostgreSQLはMS SQL Serverにはないと認識しています。サブクエリでの共通テーブルの表現

SELECT a.*, b.* 
FROM (WHERE aa as (
      <<select_query>), 
      SELECT * 
      FROM aa 
      WHERE <<criteria>> 
    ) as a 
    LEFT JOIN (
     WITH bb as (
      <<select_query> 
     ), 
     select * from bb inner join tbl_c on <<innerjoin>> where <<criteria>> 
    ) as b 
    on <<join_expr>> 

サブクエリの外側にwith句を定義できません。両方のクエリが動的に生成されます。w.r.t. また、上記のクエリ自体を別のクエリでサブクエリとして使用することもできます。 要約すると、原理は動的に生成されたビューであり、後で再利用可能です。一部のクエリでは、このような動的ビューも一緒にマージされるまで最大で10-12回ある可能性があります。 問題は、少なくともPG、Oracle & DB2に関する限り、アプリケーションはデータベースに依存しないと考えられており、DB2によってサポートされていない機能はまったく実装されていないということです。直接あなたの質問への答えはありませんが、多分あなたはこのことについて考えることができ

+2

Oracleはそれを「サブクエリ・ファクタリング」と呼び、それを使用してサブクエリ内で定義すると、貧しい選択肢として私を襲います。高くなるほど、使用範囲が広がります。 –

答えて

3

は:

SQL Serverは、それがそうすることは理にかなっているSQLのセマンティクス(必ずしも構文)を制限しているようです。たとえば、TOP n句を指定しない場合は、ORDER BY句のサブクエリを使用することはできません。順序付きサブクエリには制限がない限り無意味なので、これは理にかなっています。他のRDBMSはそのような無意味さを許容します。

CTEが最上位レベルで宣言されるようにクエリ全体を書き直すことができるため、サブクエリでCTEを使用することは意味がありません。唯一の違いは、各宣言の範囲とおそらく可読性です。一方

、CTEのは、CTEのは、サブクエリ内で宣言されているときに適用することは非常に困難であるかもしれない、再帰クエリを可能に...

あなたはデータベースに依存しないSQLを実装する必要があるので、私はあなたがいないお勧めしますまだCTEを多用しています。 CTEが単純な場合は、単純なビューとしていつでも書き直すことができます。

+0

現時点では、それは私たちが現時点でやるべきことです。しかし、内部クエリで "WITH"をサポートする他のRDBMSについてコメントすることはできますか? – Kapil

+0

@カピル、残念ながら、私はこれ以上あなたに話すことはできません。私はネストされたクエリでまだ 'WITH'句を使用しようとしていません。しかし、CTEが再帰的でない場合、一般的な問題ではないと私は考えています。 –

4

はい、OracleのサブクエリでCTEを使用できます。 Oracle 11g docsから:

あなたは、任意のトップレベルのSELECT文でサブクエリとの ほとんどの種類でこの句を指定することができます。問合せ名は、メイン問合せ およびそれ以降のすべてのサブクエリに表示されます。再帰的サブクエリファクタリングの場合、 クエリ名はクエリ の名前自体を定義するサブクエリに表示されます。一例として、

、これは、Oracleで動作します。

SELECT a.*, b.* 
    FROM (WITH aa AS 
     (
      SELECT LEVEL l1, mod(level, 5) m1 FROM dual CONNECT BY LEVEL < 50 
     ) 
     SELECT * FROM aa WHERE m1 < 3) a LEFT JOIN 
     (WITH bb AS 
     (
      SELECT LEVEL l2, mod(level, 5) m2 FROM dual CONNECT BY LEVEL < 50 
     ) 
     SELECT * FROM bb WHERE m2 BETWEEN 1 AND 4) b 
     ON a.l1 = b.l2; 
0

新しいMicrosoft SQL Serverのバージョンは、CTEのをサポートしています。

+0

ビットは依然として問題のサブクエリcteをサポートしていません:http://stackoverflow.com/questions/1914151/how-we-can-use-cte-in-subquery-in-sql-server) – Vadzim

0

PostgreSQLはCTEをサポートしていますが、これは述語を妨げたり、CTEクエリに参加することを妨げる最適化の障壁です。これにより、単純なサブクエリよりも効果が少なくなります。

関連する問題