【问题标题】:LEFT OUTER JOIN (gives extra rows) problemLEFT OUTER JOIN(提供额外的行)问题
【发布时间】:2010-12-15 09:31:01
【问题描述】:

我有两个表,我想使用左外连接将它们连接在一起。然而,即使我的左表仅包含唯一值,右表也不止一次满足 CONDITION,因此,向结果集中添加了额外的行。

复制问题的代码:

声明@tb1 表(c1 int) 声明@tb2 表(c2 int) 插入@tb1 值 (1) 插入@tb1 值 (2) 插入@tb1 值 (3) 插入@tb1 值 (4) 插入@tb2 值 (3) 插入@tb2 值 (4) 插入@tb2 值 (5) 插入@tb2 值 (6) select * from @tb1 left outer join @tb2 ON c1 = c2 插入@tb2 值 (3) 插入@tb2 值 (4) 插入@tb2 值 (5) 插入@tb2 值 (6) select * from @tb1 left outer join @tb2 ON c1 = c2

如您所见,第一个 SELECT 返回 4 行,第二个 SELECT 返回 6 行,尽管左表保持不变。

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

帮助!

结果: c1 c2 ------------ ------------ 1 空 2 空 3 3 4 4 [重复@tb2 记录] c1 c2 ------------ ------------ 1 空 2 空 3 3 3 3 4 4 4 4

【问题讨论】:

  • 我有一个包含多个非不同行(登录日志)的表,我的左表是按用户 ID 分组的表,因此它是不同的。右表是原始表,其中包含我需要的数据。因此,我使用 USERid 将右表链接到左表,以便我可以返回有用的数据

标签: sql join


【解决方案1】:

抱歉,您的想法有偏差。

这样想:如果您只希望 tb2 中的每一行对应 tb1 中的一行,那么服务器应该选择哪一行?事实是,从连接的定义来看,右侧表中与左侧行匹配的每一行都是匹配的,必须包含在内。

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

【讨论】:

  • 这绝对正确,因此我改变了我的想法,因此我的 ON 声明变得独一无二,从而缓解了问题。
  • 对于同一个例子,左外连接似乎在 sqlite 上返回不同的行!不知道为什么。按照@astander 的建议执行select distinct ... 可以解决该问题。
【解决方案2】:

尝试使用

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

【讨论】:

  • 这在这种简化的情况下可以工作,但我很确定实际上他的 rhs 表有更多列 - 然后 distinct 无济于事。
  • 我同意,在这种情况下,他需要决定是什么使该行“不同”,或者必须显示多行,其 id 来自表 1
  • 如何选择 distinct on (col, col)
【解决方案3】:

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

【讨论】:

  • 从 100 毫秒的执行时间开始,这一时间达到了 83 秒。
  • 您需要向我们详细说明您想要达到的目标
  • 耗时 83 秒的表有多大?您是否在实际查询中使用 LIKE 运算符?
  • 13,166,165 ROWS,200,000+ /天
【解决方案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

【讨论】:

  • 上面的例子只是一个例子,因此每个表只有一列。
  • 感谢您的回答。我正在加入 5 个记录超过 25 万条的表,而这个答案正是我所需要的。
  • 谢谢。这为我节省了一些头发。
【解决方案5】:

嗯,由于右侧表中有重复的记录(或至少重复的标识符),因此查询正在执行应有的操作。

要获得您想要的效果,例如:

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

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

【讨论】:

    猜你喜欢
    • 2013-05-02
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2010-09-29
    • 2013-03-10
    相关资源
    最近更新 更多