2016-12-07 118 views
2

是这样的可能(我知道这种说法是不工作的,我试了一下):SELECT * FROM T,其中TX或TY IN(SELECT ID FROM Z)

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?我正在使用Postgres,但我在寻找一个通用的解决方案。

回答

4

使用EXISTS

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

完美的作品...谢谢! – unwichtich

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表达式的版本可能是最有效的。

0

尝试...

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

这不一定是一样的东西 –

+0

这可能会导致重复的记录,如果id在'z'表中重复 –

+0

然后你可以在必要时使用'distinct'。 –

相关问题