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

Posted

技术标签:

【中文标题】如何在一个 PostgreSQL 查询中使用多个 WITH 语句?【英文标题】:How to use multiple WITH statements in one PostgreSQL query? 【发布时间】:2016-11-03 08:39:23 【问题描述】:

我想使用 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 documentation 并研究了使用多个 WITH 语句但无法找到答案。

【问题讨论】:

在第二个 with 语句之前尝试一个逗号,之后的任何其他语句。不确定 postgres,但这是 Oracle 和 sql server 的正常语法 我尝试使用逗号和分号,但仍然存在语法错误:ERROR: syntax error at or near "WITH" 用于逗号,ERROR: syntax error at or near ";" 用于分号。 【参考方案1】:

根据其他 cmets,第二个公用表表达式 [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 无效,因为您从未实际引用 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。如下:

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

【讨论】:

很高兴为您提供帮助。我找不到关于不使用 IN 的文章,但我强烈建议在 IN 上使用 JOIN 或 EXISTS。如果结果集中存在空值,您将获得每条记录,而不仅仅是您想要的记录。这很奇怪,但这是大多数 RDBM 的工作方式。尝试检查它的搜索,我知道我在这个网站上看到的很好的答案也是......无论如何,祝你晚安【参考方案2】:

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

【讨论】:

以上是关于如何在一个 PostgreSQL 查询中使用多个 WITH 语句?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Postgresql查询中使用多个“唯一索引推断”

postgresql:jsonb在一个查询中更新多个键

使用 PostgresQL 作为数据源在 Grafana 中进行一个查询的多个系列

PostgreSQL 查询帮助:如何检查多个列的值是不是同时增加/减少

如何在for循环中执行多个查询

如何使用 RECORD 在 PostgreSQL 中返回多行?