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


105

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ステートメントの使用について調査しましたが、答えを見つけることができませんでした。


2番目のwithステートメントの前にコンマを、その後に他のステートメントを試してください。postgresについてはよく
わかり

カンマと後でセミコロンを使用しようとしましたが、まだ構文エラーがありました:ERROR: syntax error at or near "WITH"コンマとERROR: syntax error at or near ";"セミコロン。
グレッグ

回答:


166

他のコメントによると、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-serverの人々(私自身を含む)が終了しないためです。 CTEが定義される前に終了する必要がある以前のステートメント...

ただし、WHEREステートメントに関して2番目の構文の問題があったことに注意してください。 WHERE date IN table_2table_2から値/列を実際に参照することはないため、は無効です。私が好むINNER JOIN以上INまたはExistsので、ここで動作するはず構文は次のとおりです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
;

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

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

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

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

喜んでお手伝いします。INを使用しないという記事は見つかりませんが、JOINまたはEXISTS overINを使用することを強くお勧めします。結果セットにnullが存在する場合、必要なレコードだけでなく、すべてのレコードが取得されます。これは奇妙ですが、ほとんどのRDBMの動作方法です。それで検索をチェックしてみてください、私はそれについて私が見た良い答えがこのサイトにもあったことを知っています...とにかく、おやすみなさい
Matt

8

WITHステートメントを使用して結果を連鎖させることもできます。例えば:

WITH tab1 as (Your SQL statement),
tab2 as ( SELECT ... FROM tab1 WHERE your filter),
tab3 as ( SELECT ... FROM tab2 WHERE your filter)
SELECT * FROM tab3;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.