所以我正在测试2个查询,但我得到了不同的结果。我想纠正/修补我的理解。根据我的理解,这里有两个通用的SQL查询是相同的,但执行时得到的结果不同。请注意,这不是关于diff between ANSI and non-ANSI SQL的问题。
查询1(使用LEFT JOIN
):
SELECT * FROM person p LEFT JOIN person_log pl
ON p.person_id = pl.person_id
WHERE pl.person_id IS NULL
AND p.is_active = 1;
查询2(使用2个查询):
SELECT * FROM person
WHERE person.is_active = 1
AND person_id NOT IN (SELECT person_id FROM person_log);
根据我的理解,represent this in venn diagram form。还有,比另一个更有效吗?查询JOIN
结果与2个查询?
编辑:在查询1中将=
更改为IS
。感谢@Justin Samuel发现导致不同结果的=
错误!
答案 0 :(得分:2)
上述查询中有一个错误1.您不能使用" ="检查它是否为NULL
SELECT * FROM person p LEFT JOIN person_log pl
ON p.person_id = pl.person_id
WHERE pl.person_id = NULL
AND p.is_active = 1;
理想情况下,您应该使用IS NULL
SELECT * FROM person p LEFT JOIN person_log pl
ON p.person_id = pl.person_id
WHERE pl.person_id IS NULL
AND p.is_active = 1;
您可以查看https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/
中的NULL检查答案 1 :(得分:1)
两个查询都会为您提供相同的数据。
第二个问题是解决问题的直接方法;获取所有在person_log中没有条目的人。您可以使用NOT EXISTS
子句而不是NOT IN
子句执行相同操作。 (NOT IN
有点精简,但您在子查询中选择的值不能为空,否则您根本看不到任何数据。我通常会IN
/ NOT IN
超过{{ 1}} / EXISTS
因为它们的简单,但这是个人偏好的问题。
第一个查询称为反连接。在没有很好地实现这些方法的弱数据库系统上实现与NOT EXISTS
或NOT EXISTS
查询相同的技巧。 (原因是当编写新的数据库系统时,程序员通常会将所有工作都放在连接中,因为它们非常重要并且忽略了NOT IN
和EXISTS
一段时间。)
这取决于最快执行的DBMS,IN
,NOT IN
或反连接。无论您选择哪种语法,理想的DBMS都会达到相同的执行计划。
反连接可以产生大的中间结果。使用成熟的DBMS,您不应该因为这个原因而仅使用反连接。
答案 2 :(得分:0)
如果要查找第二个表中不匹配的行,尤其是列不可为空时,请使用NOT IN。
答案 3 :(得分:0)
第一个获取所有没有日志条目的人,然后过滤掉不活动的条目。
第二个查询获取所有人。然后过滤掉非活动状态。然后获取所有日志条目。然后筛选出没有日志条目的人。
他们都将返回相同的信息。但是,出于性能原因,如果可以使用JOIN,则应避免像第二个查询。 JOIN的主要好处是索引。 WHERE中只使用一个索引,但每个JOIN将使用一个索引。