为什么要在LEFT JOIN子句中使用一个字段,然后在WHERE子句中再进行过滤呢?
为什么会在LEFT JOIN的字段上进行过滤,然后在WHERE子句中将其排除?
在关系数据库中,这是实现反连接(antijoin)的一种方式,被SQL Server术语称为反半连接(anti semi join)。它的本质是“从一个表中获取不在另一个表中的行”。
我能想到的几种实现方式有:
select cols from t1 left join t2 on t1.key=t2.key where t2.key is null
select cols from t1 where key not in (select key from t2)
select cols from t1 where not exists (select 1 from t2 where t1.key=t2.key)
甚至可以使用以下方式:
select * from t1 where key in (select key from t1 except select key from t2)
这些方法之间存在一些差异(尤其是在使用not in
时,空值处理的风险),但它们基本上都能实现相同的功能。
回答你的问题:
很难理解为什么有人会在ID上进行LEFT JOIN,然后在WHERE子句中将其设置为NULL?
正如前面提到的,为了排除在t2中存在的t1结果。
我们可以完全省略Table2吗?也就是说根本不进行连接?
如果不使用连接(或其任何等效的替代方法),你将获得更多的结果,因为与table2中的任何行具有相同ID的table1中的行也将被返回。
为什么会在LEFT JOIN的字段上进行LEFT JOIN,然后在WHERE子句中过滤它?
在上述问题中,LEFT JOIN被用于连接两个表,并获取所有没有电话号码的用户。然而,LEFT JOIN后的结果仍然包含了具有电话号码的用户。这种情况可能会导致问题,因为我们只想获取没有电话号码的用户。
这个问题的出现可能是因为在进行LEFT JOIN操作时,可能没有正确指定表的别名,导致在WHERE子句中无法正确过滤数据。为了解决这个问题,我们可以为每个表设置别名,并在查询中明确指定每个列来自哪个表。
解决方法如下所示:
SELECT t1.ID, t1.Name, t2.Phone FROM Table1 AS t1 LEFT JOIN Table2 AS t2 ON t1.ID = t2.ID WHERE t2.Phone IS NULL
通过为每个表设置别名,并在LEFT JOIN和WHERE子句中使用这些别名,我们可以正确地获取所有没有电话号码的用户。在这个解决方法中,我们使用t1和t2作为别名来代表Table1和Table2。
这样,我们就可以正确地使用WHERE子句来过滤出没有电话号码的用户,并避免了在LEFT JOIN字段上进行过滤时出现的问题。
为什么会在LEFT JOIN的字段上进行过滤然后在WHERE子句中进行过滤呢?
在这里提到的查询与以下查询基本上是等价的:
SELECT ID,Name,Phone
FROM Table1
WHERE NOT EXISTS
(SELECT 1
FROM Table2
WHERE Table1.ID = Table2.ID
)
意思是选择Table1中所有没有与Table2中的相关记录的记录。
这两个查询的执行计划很可能是相同的(个人而言,我从未见过它们产生不同执行计划的情况,但我不排除这种可能性),所以这两个查询的效率应该是相同的,而且由你来决定哪种语法更容易读懂,是使用LEFT JOIN还是使用exists语法。