在PostgreSQL中结合CTE和IN

时间:2018-09-07 17:41:35

标签: postgresql transactions common-table-expression postgresql-10 sql-in

所以我在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一起工作?

(如果不可能的话,如何获得查询结果一次并在事务中多次使用它们?)

谢谢

2 个答案:

答案 0 :(得分:1)

这总是很慢,因为在PostgreSQL中CTE是优化的围栏。

您会想要这样的东西,

SELECT *
FROM vans
WHERE EXISTS (
    SELECT
    FROM shoes
    WHERE adidas_id = 1
      AND vans_id = vans.id
)

那会更快。

答案 1 :(得分:0)

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
)