将子句放入子查询中的因素

时间:2014-05-21 04:36:10

标签: sql postgresql

我想知道它是否总是可以在SQL中通过连接到子查询来考虑where条件。例如,如果我有

select ... from a join b on ... where p and q

p仅适用于aqb,那么我是否可以重写为?

select ... from (select ... from a where p) as a join (select ... from b where q) as b on ...

谢谢!

[注意:1]我正在使用postgres以防这会影响答案。 2)可读性不是一个重要的考虑因素,因为它们是自动生成的查询。 编辑:3)我不仅对内连接感兴趣,还对其他连接感兴趣。]

2 个答案:

答案 0 :(得分:1)

我会说是的,我无法想到一个不可能的情况。在哪里可以用连接代替self:

select ... from A where x=10
<=>
select ... from A join ( values (10) ) B (x) on A.x = B.x

也许是偏离主题,但对于一般的变换,Vadim Tropashko(http://arxiv.org/abs/cs/0501053)表明可以将经典关系代数运算符集减少为两个二元运算:自然连接和广义联合

答案 1 :(得分:1)

一般来说,查询1:

SELECT ...
FROM TableA
JOIN TableB ON <SomeForeignKey>
JOIN TableC ON <SomeForeignKey>
WHERE <SomeConditionOnTableA> AND
      <SomeConditionOnTableB> AND
      <SomeConditionOnTableC>

...等同于查询2:

SELECT ...
FROM TableA
JOIN TableB ON <SomeForeignKey> AND <SomeConditionOnTableB>
JOIN TableC ON <SomeForeignKey> AND <SomeConditionOnTableC>
WHERE <SomeConditionOnTableA>

但如果使用OUTER JOIN代替(INNER)JOIN,情况也是如此。使用OUTER JOIN时,等效性适用于与NOT NULL列值匹配的非常简单的条件,例如:

name='value'
name LIKE '%value%'
number < const
field IN (...)

请注意,这些都是使OUTER JOIN无论如何都不成熟的条件,因为它们会过滤掉envolved列中包含NULL值的行...因此它们也会过滤掉OUTER JOIN添加的行而不检索任何内容来自联合表。

但是,如果使用OUTER JOIN并开始将列值与NULL进行比较或比较可能包含NULL的表达式,则等效性会中断。

例如,采用此查询(格式为查询1):

SELECT ...
FROM      TableA a
LEFT JOIN TableB b ON <SomeForeignKey>
LEFT JOIN TableC c ON <SomeForeignKey>
WHERE a.somefield = 'whatever'
  AND b.name IS NOT NULL
  AND c.somenumber >100

在这种情况下,在解析OUTER JOIN之后应用过滤器,它消除了TableB中存在的行并具有NULL名称,但也删除了OUTER JOIN添加的行没有找到匹配的行在表B中。这等同于查询2格式:

SELECT ...
FROM      TableA a
LEFT JOIN TableB b ON <SomeForeignKey> AND b.name IS NOT NULL
LEFT JOIN TableC c ON <SomeForeignKey> AND c.somenumber >100
WHERE a.somefield = 'whatever'

在这种情况下,在解析OUTER JOIN之前,过滤器将应用于TableB。具有NULL名称的TableB行将被过滤器消除,但由LEFT JOIN重新引入。因此,此查询可能包含前者不包含的行。