하나의 PostgreSQL 쿼리에서 여러 WITH 문을 사용하는 방법은 무엇입니까?


96

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문 을 사용하는 방법을 조사 했지만 답을 찾을 수 없었습니다.


두 번째 with문 앞에 쉼표를 사용하십시오 . postgres에 대해서는 확실하지 않지만 Oracle과 SQL 서버의 일반적인 구문입니다
msheikh25

나는 쉼표 나중에 세미콜론을 사용하여 시도 및 구문 오류가 여전히 있었다 : ERROR: syntax error at or near "WITH"쉼표과 ERROR: syntax error at or near ";"세미콜론을 위해.
그렉

답변:


155

다른 주석에서 두 번째 공통 테이블 표현식 [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진술 과 관련하여 두 번째 구문 문제가 있음을 유의하십시오 . WHERE date IN table_2실제로 table_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
;

일반적으로 EXISTS가 IN보다 낫지 만 IN을 사용하려면 실제 SELECT 문이 필요합니다.

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

IN은 date잠재적으로 NULL그렇게 될 수있을 때 매우 문제가 될 수 있습니다. 만약 당신이 a를 사용하고 싶지 않다면 JOIN나는 EXISTS. 다음과 같이 :

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

2
자세한 설명을 해주셔서 감사합니다. 구문이 작동했습니다. :)
Greg

기꺼이 도와 드리겠습니다. IN을 사용하지 않는 것에 대한 기사를 찾을 수 없지만 IN보다 JOIN 또는 EXISTS를 사용하는 것이 좋습니다. 결과 집합에 null이 있으면 원하는 레코드뿐만 아니라 모든 레코드를 얻을 수 있습니다. 이상하지만 대부분의 RDBM이 작동하는 방식입니다. 그것에 대한 검색을 확인해보세요. 내가 본 좋은 대답이이 사이트에도 있다는 것을 압니다 ... 어쨌든, 좋은 밤 되세요
Matt

5

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.