当a和b是CTE时,如何执行“a UNION b”?

时间:2014-08-20 18:46:38

标签: postgresql common-table-expression set-operations

如果我尝试UNION(或INTERSECT或EXCEPT)一个公用表表达式,我会在UNION附近出现语法错误。如果不是使用CTE而是直接将查询放入联合中,一切都按预期工作。

我可以解决这个问题但是对于一些使用CTE的更复杂的查询会使事情更具可读性。我也不喜欢不知道为什么会出现问题。

例如,以下查询有效:

SELECT *
FROM 
(
SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.start_point_oid

UNION

SELECT oid, route_group
FROM runs, gpspoints
WHERE gpspoints.oid = runs.end_point_oid
) AS allpoints
;

但是这个失败了: 错误:“UNION”或附近的语法错误 第20行:UNION

WITH 
startpoints AS
    (
    SELECT oid, route_group
    FROM runs, gpspoints
    WHERE gpspoints.oid = runs.start_point_oid
    ),
endpoints AS
    (
    SELECT oid, route_group
    FROM runs, gpspoints
    WHERE gpspoints.oid = runs.end_point_oid
    )
SELECT *
FROM
(
startpoints
UNION
endpoints
) AS allpoints
;

UNIONed在一起的数据是相同的,但是一个查询失败而另一个查询失败。

我在Windows 7上运行PostgreSQL 9.3。

2 个答案:

答案 0 :(得分:2)

问题是因为CTE 直接文本替换,a UNION b 无效 SELECT syntax。 SELECT关键字是解析的必需部分,语法错误在之前引发,甚至考虑了CTE。

这就是为什么

SELECT * FROM a
UNION
SELECT * FROM b

工程;语法有效,然后在表位置(通过a)使用CTE(由bwith_query_name表示)。

答案 1 :(得分:1)

至少在SQL Server中,我可以轻松地执行此操作 - 创建两个CTE,并从每个CTE中执行SELECT,并结合UNION

WITH FirstNames AS 
(
    SELECT DISTINCT FirstName FROM Person
), LastNames AS 
(
    SELECT DISTINCT LastName FROM Person
)
SELECT * FROM FirstNames
UNION 
SELECT * FROM LastNames

不确定这是否也适用于Postgres - 试一试!