如何在一个 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语句,但是找不到答案。

175859 次浏览

根据其他注释,第二个公共表表达式[ CTE ]前面是逗号,而不是 WITH语句,因此

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

根据您的实际查询,这种语法在 PostgreSql、 Oracle 和 sql-server 中应该可以工作,以后通常您将使用分号(;WTIH)处理 WITH,但这是因为通常 sql-server 用户(包括我自己)不会结束以前需要在定义 CTE 之前结束的语句..。

但是请注意,与 WHERE语句相关的还有第二个语法问题。WHERE date IN table_2无效,因为您从未实际引用表 _ 2中的值/列。我更喜欢 INNER JOIN而不是 INExists,所以这里有一个应该与 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);

date可能是 NULL时,IN 是非常有问题的,所以如果你不想使用 JOIN,那么我建议使用 EXISTS。详情如下:

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

还可以使用 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;