为什么我会在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;
答案 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
的速度有多快。