左联接位置子句不为空

时间:2019-01-16 03:42:11

标签: sql

我有两个表A和B 公用栏x

SELECT A.*
FROM A
LEFT JOIN B
ON A.x == B.x
WHERE A.z == "Hola" AND B.y IS NOT NULL;

我对与EXIST或LEFT JOIN WHERE子句相比为null会产生什么输出感到困惑。

如果我没记错的话,这需要A上的内容和A&B之间的相同之处,但排除B无效的地方,对吗?

4 个答案:

答案 0 :(得分:1)

如果表包含以下值:

**Table1**                  **Table2**    

ID       Values           ID         Values
1        100              1          10
2        200              2          20
3        300              3          30
4        400              4          40
null     2000             null       3000
5        500

您的查询将返回以下内容:

具有:A.Id, A.table1_values, B.Table2_values

ID       Table1_Values  Table2_Values
1        100            10
2        200            20
3        300            30
4        400            40
5        500            null

a.*的最终输出:

ID       Table1_Values  
1        100            
2        200            
3        300            
4        400            
5        500
null     2000

从此处复制的数据:left outer join with null values

答案 1 :(得分:1)

这是您的查询:

SELECT A.*
FROM A LEFT JOIN
     B
     ON A.x = B.x
WHERE A.z = 'Hola' AND B.y IS NOT NULL;

您需要分解查询。

结果集将只有A.Z = 'Hola'。这是WHERE子句中的重要过滤器。

然后,B.y IS NOT NULL意味着两件事:B中存在匹配项,而y不是NULL。因此,此查询等效于:

SELECT A.*
FROM A INNER JOIN
     B
     ON A.x = B.x
WHERE A.z = 'Hola' AND B.y IS NOT NULL;

使用内部联接,可以将WHERE条件放入ON中。那是风格问题。您无法使用LEFT JOIN来做到这一点。

然后,“等价” EXISTS查询将是:

SELECT A.*
FROM A 
WHERE A.z = 'Hola' AND
      EXISTS (SELECT 1 FROM B WHERE A.x = B.x AND B.y IS NOT NULL);

这些并不完全相同。如果JOIN中有多个匹配项,则带有A的版本将返回B的重复行。由于您仅从A中进行选择,因此可能不希望重复,因此建议使用EXISTS查询。

答案 2 :(得分:0)

非常简单但很好的问题。

让我们进行转换并找到答案

步骤1:将WHERE上的B.y谓词移至JOIN子句

SELECT 
    A.*
FROM 
    A
    LEFT JOIN B ON A.x == B.x
        AND B.y IS NOT NULL
WHERE 
    A.z == "Hola";

现在我们可以:

  1. LEFT JOIN转换为UNION ALLJOIN-表达式的NOT EXISTS-

步骤2:转换LEFT JOIN-> JOIN + NOT EXISTS

SELECT A.*
    FROM A
    JOIN B ON A.x == B.x
        AND B.y IS NOT NULL 
WHERE 
    A.z == "Hola" 
UNION ALL
SELECT A.*
    FROM A
WHERE 
    A.z == "Hola"
    AND NOT EXISTS(
        SELECT * FROM B 
            WHERE A.x = B.x                
            AND B.y IS NOT NULL
    )

看看这些表达式,我们可以看到:

  1. 在一般情况下,无法进一步简化
  2. 如果表B的所有未定义为NOT NULL-UNION ALL下半部分的字段变得多余

答案 3 :(得分:0)

您可以尝试如下操作:

select a.*
from a
where a.z = "Hola"
and exists (select 1
            from b
            where b.y is not null
            and b.x = a.x);