首页 > 解决方案 > on-clause 中的 SQLite 约束不起作用

问题描述

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。

这背后的原因是什么?或者我怎么能用谷歌搜索这个话题?感谢。

标签: sqlsqlite

解决方案


这是您的第一个查询,结构略有不同:

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并且dleft join.

如何left join工作?连接产生第一个表中的每一行以及第二个表中与每个第一个表行匹配的每一行。如果第二个表中没有行,则NULL返回值。然后这个集合被where子句过滤。

这是什么意思?如果on子句返回falseor null则仍返回第一个表中的行。让我重复一遍: 无论子句的结果如何,都会返回第一个表中的所有行。直接后果:对 a 子句中第一个表的过滤器无效(好吧,它们将返回第二个表中列的值)。ononleft joinNULL

所以,所有这些过滤都应该在where子句中。


推荐阅读