在 PostgreSQL 中结合 CTE 和 IN
Posted
技术标签:
【中文标题】在 PostgreSQL 中结合 CTE 和 IN【英文标题】:Combine CTE along with an IN, in PostgreSQL 【发布时间】:2019-02-13 02:07:38 【问题描述】:所以我在 PostgreSQL 10 中有这个简单的查询。
with bunch_of_things as (
select vans_id from shoes where adidas_id = 1
)
select * from vans where vans.id in (bunch_of_things) ;
我收到一个错误column "bunch_of_things" does not exist
我知道我可以将第一个选择放在第二个查询的括号内,以定义 IN 部分
但是由于我会在同一个事务中多次使用第一个查询的结果,所以我不想多次执行同一个查询。
那么我怎样才能使 IN 与 CTE 一起工作?
(如果这不可能,我怎样才能获得一次查询的结果并在事务中多次使用它们?)
谢谢
【问题讨论】:
【参考方案1】:CTE 的名称就像一个表格,所以你应该做一个选择
with bunch_of_things as (
select vans_id from shoes where adidas_id = 1
)
select * from vans where vans.id in (select vans_id from bunch_of_things);
但是您需要考虑几件事情。
首先,EXISTS
在性能方面通常比IN
更好
with bunch_of_things as (
select vans_id from shoes where adidas_id = 1
)
select *
from vans v
where EXISTS (
select 1
from bunch_of_things b
where b.vans_id = v.id
)
其次,在 postgres 10 及以下 CTE 中是一个性能围栏,因此 postgres 无法整体优化查询(但是 might 更改)。在某些情况下,这可能是控制查询执行的有用方法,并且绝对是您应该考虑的事情。
在事务中执行查询和重用结果的另一种方法是使用临时表,如下所示:
CREATE TEMPORARY TABLE bunch_of_things (vans_id integer)
ON COMMIT DROP;
INSERT INTO bunch_of_things (vans_id)
SELECT vans_id FROM shoes where adidas_id = 1;
然后照常使用表格:
select *
from vans v
where EXISTS (
select 1
from bunch_of_things b
where b.vans_id = v.id
)
【讨论】:
【参考方案2】:这总是很慢,因为在 PostgreSQL 中,CTE 是一个优化栅栏。
你会想要这样的东西,
SELECT *
FROM vans
WHERE EXISTS (
SELECT
FROM shoes
WHERE adidas_id = 1
AND vans_id = vans.id
)
这样会快很多。
【讨论】:
感谢您的提示。但我会多次使用嵌套子查询。那么如果我每次都定义/执行它会更快吗?谢谢以上是关于在 PostgreSQL 中结合 CTE 和 IN的主要内容,如果未能解决你的问题,请参考以下文章
在 plpgsql(PostgreSQL 的)中,可以将 CTE 保留到外循环吗?
在 SQL Server 中结合 CTE“WITH”和“WITH XMLNAMESPACES....”