【问题标题】:LEFT JOIN WHERE Clause IS NOT NULLLEFT JOIN WHERE 子句不为空
【发布时间】:2019-01-16 03:42:10
【问题描述】:

我有两张桌子 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 子句为空相比,这会产生什么输出,我感到很困惑。

如果我没记错的话,这需要 A 上的内容和 A&B 之间的共同点,但不包括 B 为空的内容,对吗?

【问题讨论】:

  • 这就像一个基于你的 where 条件排除 B 空值的内部连接。
  • 如果 B 值不为空,我认为它至少与表 A 通用

标签: sql


【解决方案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 意味着两件事:匹配存在于By 不是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);

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

【讨论】:

  • 戈登感谢您的解释!如果在 B 与 A 通用的情况下,我想将特定的 B 列值分配给 A 列值(例如:用于填充 A 中的空内容)。这种方法仍然有效吗?正如你所提到的,我想在 A 中提及重复项。
  • @Vesper 。 . .新问题应该以 questions 而不是 cmets 的形式提出。 这个问题显然是关于 select 而不是 `update。
【解决方案2】:

如果表包含以下值:

**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

【讨论】:

  • 感谢您的回答,a.* 的最终输出是什么意思?
  • @Vesper 这就是您发布的查询:SELECT A.*
【解决方案3】:

非常简单但很好的问题。

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

第 1 步:将 B.y 上的 WHERE 谓词移动到 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 转换为JOIN-NOT EXISTS- 表达式中的UNION ALL

第二步:转换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 的下部变得多余

【讨论】:

    【解决方案4】:

    你可以试试这样的:

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 2021-02-15
      • 2017-07-31
      相关资源
      最近更新 更多