左边加入Null脚本效率解释需要

时间:2017-07-25 15:18:25

标签: mysql sql sql-server

为什么我会在LEFT JOIN子句中的SQL中使用FROM并附加实体“为空”的WHERE子句?我被告知这是一个非常有效的脚本,我应该学习它背后的方法。

例如:

FROM
    something
    LEFT JOIN aRow a AND bRow b AND cRow c AND dRow d
WHERE
    bRow.b IS NULL;

2 个答案:

答案 0 :(得分:1)

当您特别想知道“所有从未订购过任何东西的客户的清单”之类的内容时,会使用这种结构:

SELECT
  customer.*
FROM
  customers
  LEFT JOIN 
  orders
  ON
    orders.customerid = customers.id
WHERE
  orders.id IS NULL

或者引用我的一位老经理:“你能让数据库给我一个不在数据库中的所有内容的列表吗?”

ME> “当然,你能给我一份数据库告诉你它没有的东西的清单吗?”

他> “我怎么知道这个?”

答案 1 :(得分:0)

这确实是一个非常通用的非RDBMS特定问题。该逻辑将适用于几乎任何SQL的风格。这是一种技术,任何使用数据查询的人都应该熟悉这种技术。

对于所有意图和目的(并且超越了OP中有缺陷的语法),这是与查询相同的查询:

SELECT *
FROM table1 
WHERE table1.col1 NOT IN ( 
    SELECT table2.col1 FROM table2 WHERE table2.col2 = <filterHere> 
)

当您处理几百行时,您可能看不到性能上的显着差异。但是当你在两个表中只使用几百万行时,你肯定会看到显着的性能提升

SELECT table1.*
FROM table1 
LEFT OUTER JOIN table2 ON table1.col1 = table2.col1
    AND table2.col2 = 42
WHERE table2.id IS NULL

让我们来说明这些查询发生了什么。

创建测试表。

CREATE TABLE table1 (col1 int, col2 varchar(10)) ;
INSERT INTO table1 ( col1, col2 )
VALUES (1,'a')
, (2,'b')
, (3,'c')
, (4,'d')

CREATE TABLE table2 (col1 int, col2 varchar(10)) ;
INSERT INTO table2 ( col1, col2 )
VALUES (1,'a')
, (3,'c')

这给了我们

table1
col1 col2
1    a
2    b
3    c
4    d

table2
col1 col2
1    a
3    c

现在我们想要table1但不在table2中的列。

SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN ( 
    SELECT t2.col1 FROM table2 t2 
)

我们不能SELECT来自table2的任何内容,因为该表只是一个子查询,而不是整个查询的一部分。它不适用于我们。

这分解为

SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN ( 1,3 )

进一步分解为

SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 <> 1
    OR t1.col1 <> 3

这些查询给我们

col1 col2
2    b
4    d

这是一个子查询,分为2个不同的OR语句来过滤我们的结果。

让我们看一下JOIN。我们想要左侧的所有记录,并且只包括匹配右侧的记录。所以

SELECT t1.col1 AS t1_col1, t1.col2 AS t1_col2, t2.col1 AS t2_col1, t2.col2 AS t2_col2 
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1

使用JOIN,我们SELECT可以使用这两个表格,因此我们可以看到tablel2中的哪些记录与table1中的哪些记录相匹配。以上给出了我们

t1_col1  t1_col2  t2_col1  t2_col2
1        a        1        a
2        b        NULL     NULL
3        c        3        c
4        d        NULL     NULL

使用额外数据,我们可以看到2和4中的col1在两个表中不匹配。我们现在可以使用简单的WHERE语句对其进行过滤。

SELECT t1.col1, t1.col2
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1
WHERE t2.col1 IS NULL

给我们

col1 col2
2    b
4    d

过滤器中没有子查询和一个语句。此外,这允许引擎的优化器制定更有效的查询计划。

当我们只处理几行时,不可能看到性能上的差异,但是将这些表乘以几百万行,你肯定会看到JOIN的速度有多快。