如何在一条PostgreSQL查询语句中使用多个WITH语句?

193
我希望使用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语句,但未能找到答案。

我已经阅读了PostgreSQL文档并研究使用多个WITH语句,但未能找到答案。


1
尝试在第二个with语句及其后面加逗号。不确定Postgres,但这是Oracle和SQL Server的正常语法。 - msheikh25
2
我尝试使用逗号和分号,但仍然出现语法错误:使用逗号时出现“ERROR: syntax error at or near "WITH"”,使用分号时出现“ERROR: syntax error at or near ";"”。 - Greg
2个回答

308

根据其他评论所述,第二个公共表达式[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而不是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,你需要在 WHERE 子句中使用实际的 SELECT 语句。

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

date可能是NULL时,使用IN非常棘手,因此如果您不想使用JOIN,我建议使用EXISTS。如下所示:

date 可能为 NULL 时,IN 函数会出现问题,因此如果您不想使用连接查询(JOIN),我建议使用 EXISTS 函数。具体如下:

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

很高兴能帮忙。我找不到关于不使用IN的文章,但我强烈建议使用JOIN或EXISTS而不是IN。如果结果集中存在空值,那么你将得到每条记录,而不仅仅是你想要的记录。这很奇怪,但大多数RDBMs都是这样工作的。尝试在搜索引擎上查找一下,我知道我看到的好答案也在这个网站上...无论如何,晚安。 - Matt

30

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

你有没有推荐的学习“filter”使用的资源? - TD1
2
在这个上下文中,“filter”是“WHERE”子句的条件,即SQL布尔表达式。您可以在文档和在线教程中查看详细信息和示例。使用测试数据库进行实验是学习的好方法。 - Nagev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接