也许是一个愚蠢的问题,但请考虑这两个表:
T1
Store Year
01 2009
02 2009
03 2009
01 2010
02 2010
03 2010
T2
Store
02
为什么这个INNER JOIN会给我我想要的结果(过滤ON子句中的[year]):
select t1.*
from t1
inner join t2
on t1.store = t2.store
and t1.[year] = '2009'
Store Year
02 2009
为什么LEFT OUTER JOIN包含2010年的记录?
select t1.*
from t1
left outer join t2
on t1.store = t2.store
and t1.year = '2009'
where t2.store is null
01 2009
03 2009
01 2010
02 2010
03 2010
我必须在'WHERE'子句中写下[year]过滤器:
select t1.*
from t1
left outer join t2
on t1.store = t2.store
where t2.store is null
and t1.year = '2009'
01 2009
03 2009
就像我说的,也许是一个愚蠢的问题,但它让我烦恼!
答案 0 :(得分:3)
如果按照LEFT JOIN的定义
现在意识到存在等价于ON条件评估为真,这一切都有意义。
对于t1.year为2010的行,on表达式的计算结果为false(对于t1.year = 2010的所有行,x AND 2010 = 2009为false),但由于它是左连接,因此左表中的行将为仍然被退回(根据定义)。
因此,这种情况只能写为条件而不是连接条件。
(一般情况下,它不必是表格而是选择表达式)
编辑: 正如Erwin有趣地指出的那样,where条件可以转换为JOIN with
select t1.*
from t1
left outer join t2
on t1.store = t2.store
or t1.year = '2009'
where t2.store is null
,因为:
t1.store t1.year t2.store t1.store=t2.store t1.year=2009 join(OR)
01 2009 02 false true true
02 2009 02 true true true
03 2009 02 false true true
01 2010 02 false false false
02 2010 02 true false true
03 2010 02 false false false
因此,只有上表中连接列为 false 的行才会在t2。*字段中返回空值。
我想说的是,这种情况不能转变为纯连接,因为左连接的工作方式(即使连接条件为假,仍会返回记录),尽可能具有内连接条件(可以转换为纯连接,反之亦然)。
关于提议的查询 - 我的建议是不要使用它。
使用OR的查询比使用AND条件作为一般规则的查询表现更差(或者扩展结果集; ANDs限制)。这适用于连接条件和条件。
你的查询会比where条件中的t1.year ='2009'查询更糟糕,因为在以后的情况下可以使用索引(如果存在),因为如果你像你一样加入,你基本上人为地将一个表中的记录与来自另一个表的记录连接起来,这样你的where条件只过滤你需要的记录。 仅从2009年开始的t1获取记录应该更有效(假设年份的指数和选择性足够高,将在WHERE条件下发生)。
关于性能的这两个建议都可以并且应该通过检查查询计划来验证。
最后,查询有点模糊 - 在t1.year ='2009'的情况下,连接变成笛卡尔积(后来被滤除)并不是很明显。因此,如果假设简单LEFT JOIN
与where t1.year = 2009 AND t2.store is null
执行得更好且更易读,我就不会使用此查询。
答案 1 :(得分:0)
你的第二个查询返回第一个表中的所有结果,除了在连接中匹配的结果(其结果可以在第一个查询中看到。)如果你拿走“where t2”,你可能更容易想象.store为null“子句,并将”t2.Store“添加到所选列。您应该看到的结果是:
01 2009 null
02 2009 02
03 2009 null
01 2010 null
02 2010 null
03 2010 null
如您所见,如果您过滤到t2.store为空的行,那么您所做的只是减去第二行(唯一一个与join子句匹配的行)。