【发布时间】:2011-02-25 04:19:36
【问题描述】:
我正在尝试比较两个表以在每个表中查找不在另一个表中的行。表 1 有一个 groupby 列,用于在表 1 中创建 2 组数据。
groupby number
----------- -----------
1 1
1 2
2 1
2 2
2 4
表 2 只有一列。
number
-----------
1
3
4
所以表 1 在第 2 组中的值为 1,2,4,表 2 的值为 1,3,4。
加入第 2 组时,我希望得到以下结果:
`Table 1 LEFT OUTER Join Table 2`
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
2 2 NULL
`Table 2 LEFT OUTER Join Table 1`
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
NULL NULL 3
我可以让它工作的唯一方法是,如果我为第一个连接放置一个 where 子句:
PRINT 'Table 1 LEFT OUTER Join Table 2, with WHERE clause'
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table1
LEFT OUTER join table2
--******************************
on table1.number = table2.number
--******************************
WHERE table1.groupby = 2
AND table2.number IS NULL
以及第二个 ON 中的过滤器:
PRINT 'Table 2 LEFT OUTER Join Table 1, with ON clause'
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table2
LEFT OUTER join table1
--******************************
on table2.number = table1.number
AND table1.groupby = 2
--******************************
WHERE table1.number IS NULL
谁能想出一种方法,不在 on 子句中而是在 where 子句中使用过滤器?
上下文是我在数据库中有一个暂存区,我想识别新记录和已删除的记录。 groupby 字段相当于一个提取的批次ID,我将临时表中的最新提取与昨天存储在分区表中的批次进行比较,该表也包含所有先前提取的批次。创建表 1 和表 2 的代码:
create table table1 (number int, groupby int)
create table table2 (number int)
insert into table1 (number, groupby) values (1, 1)
insert into table1 (number, groupby) values (2, 1)
insert into table1 (number, groupby) values (1, 2)
insert into table2 (number) values (1)
insert into table1 (number, groupby) values (2, 2)
insert into table2 (number) values (3)
insert into table1 (number, groupby) values (4, 2)
insert into table2 (number) values (4)
编辑:
更多上下文 - 根据我放置过滤器的位置,我会得到不同的结果。如上所述,where 子句在一种状态下给了我正确的结果,在另一种状态下给了我正确的结果。我正在寻找一种一致的方式来做到这一点。
在哪里 -
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table1
LEFT OUTER join table2
--******************************
on table1.number = table2.number
--******************************
WHERE table1.groupby = 2
AND table2.number IS NULL
结果:
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
2 2 NULL
开-
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table1
LEFT OUTER join table2
--******************************
on table1.number = table2.number
AND table1.groupby = 2
--******************************
WHERE table2.number IS NULL
结果:
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
1 1 NULL
2 2 NULL
1 2 NULL
在哪里(这次是表2)-
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table2
LEFT OUTER join table1
--******************************
on table2.number = table1.number
AND table1.groupby = 2
--******************************
WHERE table1.number IS NULL
结果:
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
NULL NULL 3
开启 -
select table1.groupby as [T1_Groupby],
table1.number as [T1_Number],
table2.number as [T2_Number]
from table2
LEFT OUTER join table1
--******************************
on table2.number = table1.number
--******************************
WHERE table1.number IS NULL
AND table1.groupby = 2
结果:
T1_Groupby T1_Number T2_Number
----------- ----------- -----------
(0) rows returned
【问题讨论】:
-
为什么将条件从
JOIN子句移到WHERE子句很重要?当您想要这种类型的行为时,将谓词放在JOIN中是很正常的事情。 -
将它移动到 where 子句并不重要,因为对于我将表 1 连接到表 2 的第一个连接,如果我将过滤器放在 on 而不是 in,我会得到不同的结果在哪里。 PRINT 'Table 1 LEFT OUTER Join Table 2, with WHERE clause' select table1.groupby as [T1_Groupby], table1.number as [T1_Number], table2.number as [T2_Number] from table1 LEFT OUTER join table2 --**** ****************************** on table1.number = table2.number AND table1.groupby = 2 --******** ************************ WHERE --table1.groupby = 2 AND table2.number IS NULL 仅给出 null
-
那么,你想要哪一个?听起来 NULL-join 符合您的意思。这是执行此类查询的标准方法,通常比子查询替代方案更可取。我认为尝试将条件推入 WHERE 子句没有任何好处。
-
请检查我添加的编辑部分 - 可能会更好地解释。
-
SQL-92 令人憎恶。