【问题标题】:Understanding SQL self-join了解 SQL 自联接
【发布时间】:2013-03-04 03:59:32
【问题描述】:

我正在尝试了解 SQL 自联接。我有下表“人员”,其中包含员工的名字、姓氏、地址和城市(来源 W3Schools):

mysql> select * from persons;
+------+-----------+-----------+--------------+-----------+
| P_id | LastName  | FirstName | Address      | City      |
+------+-----------+-----------+--------------+-----------+
|    1 | Hansen    | Ola       | Timoteivn 10 | Sandnes   | 
|    2 | Svendson  | Tove      | Borgvn 23    | Sandnes   |
|    3 | Pettersen | Kari      | Storgt 20    | Stavanger |
+------+-----------+-----------+--------------+-----------+

我现在想返回与“Hansen Ola”同城的员工姓名。所以我写了一个自加入,它工作正常:

mysql> select p1.Lastname, p1.firstname from persons p1, persons p2 where p1.city =    p2.city and p2.lastname = 'Hansen';
+----------+-----------+
| Lastname | firstname |
+----------+-----------+
| Hansen   | Ola       |
| Svendson | Tove      |
+----------+-----------+

但是,如果我将别名 p2 更改为 p1,即 p2.lastname = 'Hansen' 更改为 p1.lastname = 'Hansen',那么我不会得到这两名员工的姓名。

mysql> select p1.Lastname, p1.firstname from persons p1, persons p2 where p1.city = p2.city and p1.lastname = 'Hansen';
+----------+-----------+
| Lastname | firstname |
+----------+-----------+
| Hansen   | Ola       |
| Hansen   | Ola       |
+----------+-----------+

有人可以帮我理解为什么将别名从 p2 更改为 p1 会改变结果吗?谢谢你。

【问题讨论】:

    标签: mysql join self-join


    【解决方案1】:

    让我突出显示您的查询,希望它更有意义:

    select p1.lastname, ...
    from persons p1, persons p2
    where ... and p1.lastname = 'Hansen'
    

    因此,您将结果限制为仅返回第一个表 p1 中的记录。同时,您将第一个表限制为只有 lastname = 'Hansen' 的表。如果您描绘了不受限制的结果集,它可能更有意义(我删除了 WHERE 子句的模糊部分以显示完整的产品):

    select p1.Lastname as p1_lastname, p2.lastname as p2_lastname
    from persons p1, persons p2
    where p1.city = p2.city
    
    P1_LASTNAME     P2_LASTNAME
    Hansen  Hansen
    Svendson    Hansen
    Hansen  Svendson
    Svendson    Svendson
    Pettersen   Pettersen
    

    如果您采用上述结果集并添加条件p1.lastname = "Hansen",那么您只会从中得到“Hansen”也就不足为奇了。

    【讨论】:

      【解决方案2】:

      这个查询有点奇怪,我不确定它在现实中有什么依据。本质上,它将一个表与自己的城市列匹配,然后指定其中一个表的lastname,这限制了结果。如果您执行SELECT * 而不是只选择有限的行,您可以看到该表正在与其自身交叉连接,并且它返回由citylastname 要求过滤的行的叉积。实际结果是:

      p1.firstname, p1.lastname, p2.firstname, p2.lastname
      Hansen        Ola          Hansen        Ola
      Hansen        Ola          Svendson      Toda
      

      由于条件颠倒,这在原始查询中被颠倒了。

      【讨论】:

      • 感谢您的解释。
      【解决方案3】:

      您的查询仅返回那些包含“Hansen”的行。它没有跟随自我加入。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-23
        • 2022-01-16
        • 1970-01-01
        • 2021-09-29
        相关资源
        最近更新 更多