LEFT OUTER JOIN(给出额外的行)问题

时间:2009-11-11 09:04:39

标签: sql join

我想要使用左外连接将两个表连接在一起。但是,即使我的左表只包含唯一值,右表也不止一次地满足CONDITION,因此会在结果集中添加额外的行。

复制问题的代码:

declare @tb1 table (c1 int)
declare @tb2 table (c2 int)

INSERT INTO @tb1 VALUES (1)
INSERT INTO @tb1 VALUES (2)
INSERT INTO @tb1 VALUES (3)
INSERT INTO @tb1 VALUES (4)

INSERT INTO @tb2 VALUES (3)
INSERT INTO @tb2 VALUES (4)
INSERT INTO @tb2 VALUES (5)
INSERT INTO @tb2 VALUES (6)

select * from @tb1 left outer join @tb2 ON c1 = c2

INSERT INTO @tb2 VALUES (3)
INSERT INTO @tb2 VALUES (4)
INSERT INTO @tb2 VALUES (5)
INSERT INTO @tb2 VALUES (6)

select * from @tb1 left outer join @tb2 ON c1 = c2

正如您所看到的,第一个SELECT返回4行,其中第二个SELECT 6,尽管左表保持不变。

如何对左表保持严格,只使用右表来补充左表中的行?

HELP!

RESULTS:
c1          c2
----------- -----------
1           NULL
2           NULL
3           3
4           4

[DUPLICATE @tb2 records]

c1          c2
----------- -----------
1           NULL
2           NULL
3           3
3           3
4           4
4           4

5 个答案:

答案 0 :(得分:14)

很抱歉,但你的想法有所偏差。

以这种方式思考:如果你只想从tb2为tb1中的每一行提供一行,服务器应选择哪一行?事实上,从连接的定义来看,右侧表中与左侧行匹配的每一行都是匹配的,必须包含在内。

在连接之前,您必须确保tbl2具有c2的不同值。如果您的SQL变体支持DISTINCT [column](并非全部都支持),Murph的建议可能会这样做。

答案 1 :(得分:4)

尝试使用

select DISTINCT * from @tb1 left outer join @tb2 ON c1 = c2

答案 2 :(得分:4)

如果您想在左侧只保留一行,则需要为左侧的每个唯一值确定要在右侧显示的内容。例如,如果要显示计数,则可以执行以下操作:

select b1.c1, x.c from @tb1 b1 
left outer join 
(
  select c2, count(*) as c 
  from @tb2
  group by c2
) as x 
ON b1.c1 = x.c2

或者如果你只是想要从c2中出现一个值:

select b1.c1, x.c2 from @tb1 b1 
left outer join 
(
  select c2
  from @tb2
  group by c2
) as x 
ON b1.c1 = x.c2

答案 3 :(得分:4)

嗯,由于右侧表中有重复记录(或至少重复的标识符),查询正在按照预期进行操作。

要获得您想要的效果:

SELECT * FROM @tb1 LEFT OUTER JOIN (SELECT DISTINCT c2 FROM @tb2) t2 ON @tb1.c1 = t2.c2

如果这还不够,您需要更详细地解释一下这个要求。

答案 4 :(得分:3)

从@ tb1中选择distinct *从左外连接@ tb2 ON c1 = c2