SQL#1
select doc.doc_id, doc.content, link, words.words
from doc left join words
on doc.doc_id = words.doc_id and words.words = "foo" and doc.doc_id < 1538766632412
where doc.content like "%foo%" and words.words is null
order by doc.doc_id desc limit 10
SQL#2
select doc.doc_id, doc.content, link, words.words
from doc left join words
on doc.doc_id = words.doc_id and words.words = "foo"
where doc.content like "%foo%" and words.words is null and doc.doc_id < 1538766632412
order by doc.doc_id desc limit 10
SQL#1的结果未考虑“ doc.doc_id <1538766632412”。但约束在SQL#2中确实有效。而且我在SQLite文档中发现,“如果存在ON子句,则笛卡尔乘积的每一行都会将布尔表达式作为布尔表达式来评估ON表达式。从该数据集中仅将表达式评估为true的行包括在内。”根据DOC,该表达式应在SQL#1中的此类记录上返回false。
这是什么原因?或者我该如何搜索这个主题? 谢谢。
答案 0 :(得分:2)
这是您的第一个查询,结构有所不同:
select d.doc_id, d.content, ?.link, w.words
from doc d left join
words w
on d.doc_id = w.doc_id and w.words = 'foo' and
d.doc_id < 1538766632412
where d.content like '%foo%; and w.words is null
order by d.doc_id desc
limit 10;
我看到的是d.doc_id < 1538766632412
子句中on
的条件-d
是left join
中的第一张表。
left join
的工作方式是什么?联接产生第一张表中的每一行以及第二张表中与第一张表的每一行匹配的每一行。如果第二个表中没有行,则返回NULL
值。然后,该集合由where
子句过滤。
这是什么意思?如果on
子句返回false
或null
,则仍返回第一个表中的行。让我重复一遍:无论on
子句的结果如何, 都将返回第一个表中的所有行。直接结果:on
子句中第一个表上的过滤器对于left join
无效(嗯,它们将为第二个表中的列返回NULL
值)。
因此,所有此类过滤都应在where
子句中。