【问题标题】:What is the maximum # of rows in a LEFT OUTER JOIN? [duplicate]LEFT OUTER JOIN 中的最大行数是多少? [复制]
【发布时间】:2019-03-10 11:19:05
【问题描述】:

对于任何两个给定的表,假设表 1 有 i 行,表 2 有 j 行,有人可以向我解释一下我们如何最终可能在 @ 中总共有 i * j 行987654324@ 如果表 1 是“左”表?我一直认为LEFT OUTER JOIN 总是会返回左表中的总行数?

【问题讨论】:

  • 听起来你以某种方式创建了一个交叉连接。如果您提供 SQL 查询,人们可以提供帮助
  • 嗨。这是一个常见问题解答。请始终在谷歌上搜索您的问题/问题/目标的许多清晰、简洁和具体的版本/措辞,带和不带您的特定字符串/名称,并阅读许多答案。将您发现的相关关键字添加到搜索中。如果您没有找到答案,请发布,使用 1 个变体搜索作为标签的标题和关键字。请参阅向下投票箭头鼠标悬停文本。 PS 了解 LEFT JOIN 返回的内容:INNER JOIN 行加上由 NULL 扩展的不匹配的左表行。作为 LEFT JOIN 的一部分,始终知道您想要什么 INNER JOIN。
  • PS 您的期望可能假设从左表到右表的 FK 以及相应 FK-PK 列相等的连接。

标签: sql oracle join left-join dml


【解决方案1】:

在内连接中,对于“左”表中的每一行,输出中的行数将与“右”表中的匹配行一样多(匹配连接条件, 那是);这可以是0j 之间的任何值。因此,内部连接可能会返回 0i*j 行之间的任何位置。顺便说一句,两者都是可能的;只需考虑连接条件 null is not null(获取 0 行)或 null is null(获取笛卡尔连接)。

outer 连接(特别是左外连接)的唯一区别是,对于“左”表中的每一行,输出中至少有一行 - 即使有右表中没有匹配的行。这就是外连接的意思。所以唯一的区别是,在左外连接中,输出将有ii*j 之间的行,而且两者都是可能的(使用与上述相同的连接条件)。

关于获取最大行数的问题 - 对于一个更“自然”的示例,假设两个表都有一个列 purchase_date,并且由于某种原因,两个表中的所有行都完全相同(非空) 列中的日期。然后,如果您加入 left_table.purchase_date = right_table.purchase_date,您将获得笛卡尔连接,其中包含 i*j 行。

【讨论】:

    【解决方案2】:

    left join 返回第一个表中的所有行。对于每一行,它返回第二个表中与on 条件匹配的所有行。如果没有行与on 条件匹配,则仍返回第一个表中的行,而其他列NULL 已删除。

    所以,如果你想要 i * j 行,就这样做:

    from t1 left join
         t2
         on 1 = 1
    

    【讨论】:

    • 我想知道我们怎么可能以 i * j 结束,而不是我如何获得 i * j 行......但我想你的回答有点涵盖它(编辑问题反映这一点)
    • @GdgamesGamers 。 . .我认为这回答了这个问题。
    • 左连接一般不会返回仅包含左表列的行,因此“左连接返回第一个表中的所有行”&“它返回第二个表中的所有行“没有意义。像他们这样你没有写的东西是有道理的。写作应该总是清晰的,但由于@GdgamesGamers 不理解像左连接这样基本的东西——可能是因为阅读了这种无处不在的不清楚的写作——缺乏清晰的问题就更成问题了。
    • @philipxy 您似乎错过了 Gordon 语句的结尾 - “它返回第二个表中与 on 条件匹配的所有行”。
    • @Boneist 您的评论不反映我写的内容或您引用的句子的实际内容。那个更长的引用比我引用的更混乱。左连接返回的行都不是来自任一输入表的行。某些输入行以某种方式在结果行中显示为 subrows。 “你没有写的像他们这样的东西是有道理的。” PS我确实不小心误导性地说“一般不”而不是“不”(与SQL表不同的关系可以有零列)和“左表”而不是“任一输入表”(编辑后的草率校对。)
    【解决方案3】:

    总行数可以是 i * j 或小于 i * j,具体取决于连接条件和数据。这里有2个例子。

    CREATE TABLE t1(
       id   VARCHAR(1)
    );
    
    INSERT INTO t1(id) VALUES ('a');
    INSERT INTO t1(id) VALUES ('b');
    INSERT INTO t1(id) VALUES ('c');
    INSERT INTO t1(id) VALUES ('d');
    
    CREATE TABLE t2(
       id       VARCHAR(1)
      ,col2 INTEGER
    );
    
    INSERT INTO t2(id,col2) VALUES ('a',1);
    INSERT INTO t2(id,col2) VALUES ('a',2);
    INSERT INTO t2(id,col2) VALUES ('a',3);
    INSERT INTO t2(id,col2) VALUES ('a',4);
    INSERT INTO t2(id,col2) VALUES ('d',1);
    

    以下查询产生的计数为 20,相当于 cross join,但这是意外由于不精确的连接条件

    select 'query 1', count(*) rows
    from t1
    left join t2 on t2.col2 > 0
    ;
    

    t2 中的所有行的 col2 > 0,因此 t1 的每一行都与 t2 中的每一行相乘(4 t1 行 * 5 t2 行 = 连接结果中的 20 行)。

    以下查询产生的计数为 7,小于 i * j,因为 连接条件是精确的

    select 'query 2', count(*) rows
    from t1
    left join t2 on t1.id = t2.id and t2.col2 > 0
    ;
    
    1. t1 中的“a”与 t2 中的“a”匹配(4 行)
    2. t1 中的'b','c' 不匹配(2 行)
    3. 'd' 匹配但仅匹配 t2 中的 1 行(1 行)
    4. 所以,总共 4 + 2 + 1 = 7 行

    【讨论】:

      猜你喜欢
      • 2013-03-10
      • 2010-11-26
      • 2012-08-07
      • 2010-09-29
      • 1970-01-01
      • 2016-04-23
      • 2012-06-21
      • 1970-01-01
      相关资源
      最近更新 更多