【问题标题】:SQL LEFT JOIN behaviourSQL 左连接行为
【发布时间】:2020-01-22 12:03:05
【问题描述】:

尝试获取 SQL LEFT JOIN 以在另一个表中没有相应行的情况下返回 NULL。

表 1 - T1

id  n
1   aaa       
2   bbb       
3   ccc       

表 2 - T2

t1_id   t3_id
1   1
2   1
3   1
1   2
3   2
2   3
3   3

在 T2 中,注意没有 2 - 2 或 1 - 3 的组合。

select * 
from t1
left join t2
on t1.id = t2.t1_id
order by t2.t3_id, t1_id

输出:

id  n   t1_id   t3_id
1   aaa         1   1
2   bbb         2   1
3   ccc         3   1
1   aaa         1   2
3   ccc         3   2
2   bbb         2   3
3   ccc         3   3

我原以为会有另外两行

1   aaa         null    null
2   bbb         null    null

...对应于前面提到的 T2 中缺失的组合。

注意 ORDER BY 只是为了方便 - 它对返回的行没有影响。

请帮助我了解为什么会发生这种情况,以及如何解决它。

【问题讨论】:

    标签: sql tsql left-join sql-null


    【解决方案1】:

    如果你想要结果集中t2中的所有行,它应该是left join中引用的第一个表:

    select * 
    from t2 left join
         t1
         on t1.id = t2.t1_id
    order by t2.t3_id, t2.t1_id;
    

    编辑:

    您似乎想要生成原始数据中没有的新行。使用cross join 生成行,然后使用left join 将它们引入:

    select t3.t3_id, t1.id, t1.n
    from (select distinct t2.t3_id from t2) as t3 cross join
         t1 left join
         t2
         on t3.t3_id = t2.t3_id and t2.t1_id
    

    【讨论】:

    • 谢谢@GordonLinoff。我已经尝试了这种变体,以及下面使用 RIGHT JOIN 的变体,并且都没有显示 NULL 行。需要明确的是,我期望返回 9 行。目前只返回 7 行。
    • @DerekBez 。 . .您想要生成不在数据中的行。查看编辑。
    • 是的! (不要忘记将 t2.t1_id = t1.id 添加到已编辑查询的末尾。)我还将 t2.* 添加到 SELECT 中,这证明您的(已编辑)解决方案是正确的 - 我需要它们的地方是 NULL。再次感谢。
    【解决方案2】:

    或者,如果您确实想在 FROM 中首先引用 t1,则可以使用 RIGHT JOIN涉及表):

    SELECT * 
    FROM t1
         RIGHT JOIN t2 ON t1.id = t2.t1_id
    ORDER BY t2.t3_id,
             t1_id;
    

    【讨论】:

      【解决方案3】:
      table1:
      -------------
      | id | name |
      -------------
      |  1 | john |
      -------------
      |  2 | mark |
      -------------
      |  3 | will |
      -------------
      
      table2:
      -----------------
      | t1_id | t3_id |
      -----------------
      |   1   |   3   |
      -----------------
      |   1   |   2   |
      -----------------
      |   3   |   1   |
      -----------------
      

      如果我想通过table2获取table1:

      SELECT t1.* 
      FROM table2 as t2 
      LEFT JOIN table1 as t1
      ON t1.id = t2.t1_id
      WHERE 1
      ORDER BY t1.id ASC;
      

      你会得到:

      -------------
      | id | name |
      -------------
      |  1 | john |
      -------------
      |  1 | john |
      -------------
      |  3 | will |
      -------------
      

      编辑:

      所以查询将得到table2中的所有内容,所以(t1_id:1,t3_id:3),(t1_id:1,t3_id:2),(t1_id:3,t3_id:1),然后左连接将比较t1 的 id 与 t2 中的 t1_id 并返回 t1 中的所有列,因为我写 *.

      【讨论】:

      • 谢谢@moemenRajab。在您的 T2 中,按如下方式更改数据行:1 - 3、1 - 2、3 - 1。删除 WHERE 子句。是否返回了三行?
      • @DerekBez 我改变了它,这就是你会得到的
      猜你喜欢
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 2021-12-27
      • 2015-09-30
      • 2021-09-02
      • 1970-01-01
      相关资源
      最近更新 更多