SELECT * FROM t WHERE t.x或t.y IN(SELECT id FROM z)

时间:2016-12-07 11:51:41

标签: sql postgresql

这样的事情是可能的(我知道这个说法不起作用,我试过了):

SELECT * FROM t WHERE t.x OR t.y IN (SELECT id FROM z)

实施例

表t:

|id|x  |y
|1 |101|201 
|2 |102|202

表z:

|id  |
|101 | 
|201 |

从这张表中我想选择属性x或属性y包含在表z的id列表中的所有条目。

我知道我能做到

SELECT * FROM t WHERE t.x IN (SELECT id FROM z) OR t.y IN (SELECT id FROM z)

但是当IN值来自复杂的子查询(在IN子句中都是相同的)时,这感觉非常低效。

或者当前的查询规划器实现是否足够聪明,以确定两个子查询都给出相同的结果并且只执行一次?或者可能还有另一个使用EXISTS的解决方案,我目前看不到?

PS:我使用Postgres,但我正在寻找通用的解决方案。

3 个答案:

答案 0 :(得分:4)

使用EXISTS

SELECT * FROM t WHERE exists (SELECT 1 FROM z where z.id in (t.x,t.y))

答案 1 :(得分:1)

如果z是一个复杂的查询,那么您可以使用CTE来简化代码:

WITH z AS (
      . . . 
     )
SELECT *
FROM t
WHERE t.x IN (SELECT id FROM z) OR t.y IN (SELECT id FROM z);

您也可以使用JOINEXISTS代替:

SELECT *
FROM t
WHERE EXISTS (SELECT 1
              FROM z
              WHERE z.id IN (t.x, t.y)
             );

JOIN版本的缺点是,由于z中的重复行,行可以成倍增加。

也就是说,具有两个IN表达式的版本可能效率最高。

答案 2 :(得分:0)

...试

SELECT t.* FROM t join z on t.x = z.id or t.y = z.id