web-dev-qa-db-ja.com

1つのPostgreSQLクエリで複数のWITHステートメントを使用するにはどうすればよいですか?

WITHステートメントを使用して、事実上複数のTEMPテーブルを「宣言」したいと思います。私が実行しようとしているクエリは、次の行に沿っています:

WITH table_1 AS (
SELECT GENERATE_SERIES('2012-06-29', '2012-07-03', '1 day'::INTERVAL) AS date
)

WITH table_2 AS (
SELECT GENERATE_SERIES('2012-06-30', '2012-07-13', '1 day'::INTERVAL) AS date
)

SELECT * FROM table_1
WHERE date IN table_2

PostgreSQLのドキュメント を読んで、複数のWITHステートメントを使用することを調査しましたが、答えが見つかりませんでした。

54
Greg

他のコメントによると、2番目の共通テーブル式[CTE]の前にはWITHステートメントではなくコンマが付いているため、

WITH cte1 AS (SELECT...)
, cte2 AS (SELECT...)
SELECT *
FROM
    cte1 c1
    INNER JOIN cte2 c2
    ON ........

実際のクエリに関しては、この構文はPostgreSql、Oracle、およびsql-serverで動作するはずです。通常は、後で[WITHをセミコロン(;WTIH)で処理しますが、これは通常sql-サーバー担当者(私自身も含む)は、CTEが定義される前に終了する必要がある以前のステートメントを終了しません...

ただし、WHEREステートメントに関して2番目の構文の問題があることに注意してください。 WHERE date IN table_2は、table_2の値/列を実際に参照することはないため無効です。 INExistsよりもINNER JOINの方が好きなので、JOINで機能する構文を以下に示します。

WITH table_1 AS (
SELECT GENERATE_SERIES('2012-06-29', '2012-07-03', '1 day'::INTERVAL) AS date
)

, table_2 AS (
SELECT GENERATE_SERIES('2012-06-30', '2012-07-13', '1 day'::INTERVAL) AS date
)

SELECT * 
FROM
     table_1 t1
     INNER JOIN 
     table_2 t2
     ON t1.date = t2.date
;

通常はEXISTSの方がINよりも優れた方法を維持したいのですが、INを使用するには、実際のSELECTステートメントがwhereに必要です。

SELECT * 
FROM
     table_1 t1
WHERE t1.date IN (SELECT date FROM table_2);

dateNULLになる可能性がある場合、INは非常に問題があるため、JOINを使用したくない場合は、EXISTSをお勧めします。次のように:

SELECT * 
FROM
     table_1 t1
WHERE EXISTS (SELECT * FROM table_2 t2 WHERE t2.date = t1.date);
93
Matt