Bir PostgreSQL sorgusunda birden çok WITH ifadesi nasıl kullanılır?


97

WITH deyimini kullanarak birden çok TEMP tablosunun etkin olarak ne olduğunu "bildirmek" istiyorum. Yürütmeye çalıştığım sorgu şu satırlar boyunca:

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 belgelerini okudum ve birden çok WITHifade kullanmayı araştırdım ve bir yanıt bulamadım.


Sonrasında withherhangi bir başkası varsa ikinci ifadeden önce virgül kullanmayı deneyin . Postgres hakkında emin değilim ama bu Oracle ve sql server ile normal sözdizimi
msheikh25

Virgül ve daha sonra noktalı virgül kullanmayı denedim ve hala sözdizimi hataları vardı: ERROR: syntax error at or near "WITH"virgül ve ERROR: syntax error at or near ";"noktalı virgül için.
Greg

Yanıtlar:


156

Diğer yorumlara göre, ikinci Ortak Tablo İfadesinin [CTE] önünde bir WITH ifadesi değil, bir virgül vardır, bu nedenle

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

Gerçek sorgunuz açısından bu sözdizimi PostgreSql, Oracle ve sql-server'da çalışmalıdır, daha sonra tipik olarak WITHnoktalı virgül ( ;WTIH) ile ilerleyeceksiniz , ancak bunun nedeni tipik olarak sql-server milletlerinin (kendim dahil) bitmemesidir. CTE tanımlanmadan önce sonlandırılması gereken önceki ifadeler ...

Bununla birlikte, ifadenizle ilgili ikinci bir sözdizimi sorununuz olduğunu unutmayın WHERE. WHERE date IN table_2geçerli değil çünkü tablo_2'den hiçbir zaman bir değere / sütuna başvurmuyorsunuz. Tercihim INNER JOINüzerinde INya Existsişte bir ile çalışmalıdır bir sözdizimi 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
;

Sahip olduğunuz yolu korumak istiyorsanız, ki bu tipik olarak MEVCUTTUR, IN'den daha iyi olur, ancak IN kullanmak için nerede olduğunuzda gerçek bir SELECT ifadesine ihtiyacınız vardır.

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

IN, ne zaman datepotansiyel olarak çok sorunlu olabilir NULLki, eğer kullanmak istemiyorsanız, JOINo zaman öneririm EXISTS. Aşağıdaki gibi:

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

2
Ayrıntılı açıklama için teşekkür ederiz, sözdizimi işe yaradı :)
Greg

Yardımcı olduğuma sevindim. IN kullanmama hakkındaki makaleyi bulamıyorum, ancak IN üzerinden bir JOIN veya EXISTS kullanmanızı şiddetle öneririm. Sonuç kümenizde bir null varsa, ne olur, sadece istediklerinizi değil her kaydı alırsınız. Garip ama çoğu RDBM'nin çalışma şekli bu. üzerinde bir aramayı kontrol etmeyi dene, bununla ilgili gördüğüm iyi cevabın da bu sitede olduğunu biliyorum ... her neyse, iyi geceler
Matt

5

Ayrıca, WITH ifadesini kullanarak sonuçlarınızı zincirleyebilirsiniz. Örneğin:

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.