自连接返回比预期更多的行

Self join returning more rows than expected

我不熟悉自连接并编写了以下示例table:

+-----------+-------------+
| name      | location    |
+-----------+-------------+
| Robert    | Guadalajara |
| Manuel    | Guadalajara |
| Dalia     | Guadalajara |
| Alejandra | Guadalajara |
| Luis      | Guadalajara |
| Monica    | Guadalajara |
| Claudia   | Guadalajara |
| Scartlet  | Guadalajara |
| Sergio    | Guadalajara |
| Rick      | Mexico City |
| Rene      | Mexico City |
| Ramon     | Culiacan    |
| Junior    | Culiacan    |
| Kasandra  | Culiacan    |
| Emma      | Culiacan    |
| Johnatha  | Dunedin     |
| Miriam    | Largo       |
| Julie     | Largo       |
+-----------+-------------+

18 行

我想 运行 一个简单的查询,将具有相同位置的人与以下查询相匹配:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1, users users2
WHERE users1.location = users2.location;

我的预期:

+-----------+-------------++-----------+-------------+                  
| name      | location    || name      | location    |
+-----------+-------------++-----------+-------------+
| Robert    | Guadalajara || Robert    | Guadalajara |
| Manuel    | Guadalajara || Manuel    | Guadalajara |
| Dalia     | Guadalajara || Dalia     | Guadalajara |
| Alejandra | Guadalajara || Alejandra | Guadalajara |
| Luis      | Guadalajara || Luis      | Guadalajara |
| Monica    | Guadalajara || Monica    | Guadalajara |
| Claudia   | Guadalajara || Claudia   | Guadalajara |
| Scartlet  | Guadalajara || Scartlet  | Guadalajara |
| Sergio    | Guadalajara || Sergio    | Guadalajara |
| Rick      | Mexico City || Rick      | Mexico City |
| Rene      | Mexico City || Rene      | Mexico City |
| Ramon     | Culiacan    || Ramon     | Culiacan    |
| Junior    | Culiacan    || Junior    | Culiacan    |
| Kasandra  | Culiacan    || Kasandra  | Culiacan    |
| Emma      | Culiacan    || Emma      | Culiacan    |
| Johnatha  | Dunedin     || Johnatha  | Dunedin     |
| Miriam    | Largo       || Miriam    | Largo       |
| Julie     | Largo       || Julie     | Largo       |
+-----------+-------------++-----------+-------------+

我得到了什么:

+-----------+-------------+-----------+-------------+
| name      | location    | name      | location    |
+-----------+-------------+-----------+-------------+
| Robert    | Guadalajara | Robert    | Guadalajara |
| Manuel    | Guadalajara | Robert    | Guadalajara |
| Dalia     | Guadalajara | Robert    | Guadalajara |
| Alejandra | Guadalajara | Robert    | Guadalajara |
| Luis      | Guadalajara | Robert    | Guadalajara |
| Monica    | Guadalajara | Robert    | Guadalajara |
| Claudia   | Guadalajara | Robert    | Guadalajara |
| Scartlet  | Guadalajara | Robert    | Guadalajara |
| Sergio    | Guadalajara | Robert    | Guadalajara |
| Robert    | Guadalajara | Manuel    | Guadalajara |
| Manuel    | Guadalajara | Manuel    | Guadalajara |
| Dalia     | Guadalajara | Manuel    | Guadalajara |
| Alejandra | Guadalajara | Manuel    | Guadalajara |
| Luis      | Guadalajara | Manuel    | Guadalajara |
| Monica    | Guadalajara | Manuel    | Guadalajara |
| Claudia   | Guadalajara | Manuel    | Guadalajara |
| Scartlet  | Guadalajara | Manuel    | Guadalajara |
| Sergio    | Guadalajara | Manuel    | Guadalajara |
| Robert    | Guadalajara | Dalia     | Guadalajara |
| Manuel    | Guadalajara | Dalia     | Guadalajara |
| Dalia     | Guadalajara | Dalia     | Guadalajara |
| Alejandra | Guadalajara | Dalia     | Guadalajara |
| Luis      | Guadalajara | Dalia     | Guadalajara |
| Monica    | Guadalajara | Dalia     | Guadalajara |
| Claudia   | Guadalajara | Dalia     | Guadalajara |
| Scartlet  | Guadalajara | Dalia     | Guadalajara |
| Sergio    | Guadalajara | Dalia     | Guadalajara |
| Robert    | Guadalajara | Alejandra | Guadalajara |
| Manuel    | Guadalajara | Alejandra | Guadalajara |
| Dalia     | Guadalajara | Alejandra | Guadalajara |
| Alejandra | Guadalajara | Alejandra | Guadalajara |
| Luis      | Guadalajara | Alejandra | Guadalajara |
| Monica    | Guadalajara | Alejandra | Guadalajara |
| Claudia   | Guadalajara | Alejandra | Guadalajara |
| Scartlet  | Guadalajara | Alejandra | Guadalajara |
| Sergio    | Guadalajara | Alejandra | Guadalajara |
| Robert    | Guadalajara | Luis      | Guadalajara |
| Manuel    | Guadalajara | Luis      | Guadalajara |
| Dalia     | Guadalajara | Luis      | Guadalajara |
| Alejandra | Guadalajara | Luis      | Guadalajara |
| Luis      | Guadalajara | Luis      | Guadalajara |
| Monica    | Guadalajara | Luis      | Guadalajara |
| Claudia   | Guadalajara | Luis      | Guadalajara |
| Scartlet  | Guadalajara | Luis      | Guadalajara |
| Sergio    | Guadalajara | Luis      | Guadalajara |
| Robert    | Guadalajara | Monica    | Guadalajara |
| Manuel    | Guadalajara | Monica    | Guadalajara |
| Dalia     | Guadalajara | Monica    | Guadalajara |
| Alejandra | Guadalajara | Monica    | Guadalajara |
| Luis      | Guadalajara | Monica    | Guadalajara |
| Monica    | Guadalajara | Monica    | Guadalajara |
| Claudia   | Guadalajara | Monica    | Guadalajara |
| Scartlet  | Guadalajara | Monica    | Guadalajara |
| Sergio    | Guadalajara | Monica    | Guadalajara |
| Robert    | Guadalajara | Claudia   | Guadalajara |
| Manuel    | Guadalajara | Claudia   | Guadalajara |
| Dalia     | Guadalajara | Claudia   | Guadalajara |
| Alejandra | Guadalajara | Claudia   | Guadalajara |
| Luis      | Guadalajara | Claudia   | Guadalajara |
| Monica    | Guadalajara | Claudia   | Guadalajara |
| Claudia   | Guadalajara | Claudia   | Guadalajara |
| Scartlet  | Guadalajara | Claudia   | Guadalajara |
| Sergio    | Guadalajara | Claudia   | Guadalajara |
| Robert    | Guadalajara | Scartlet  | Guadalajara |
| Manuel    | Guadalajara | Scartlet  | Guadalajara |
| Dalia     | Guadalajara | Scartlet  | Guadalajara |
| Alejandra | Guadalajara | Scartlet  | Guadalajara |
| Luis      | Guadalajara | Scartlet  | Guadalajara |
| Monica    | Guadalajara | Scartlet  | Guadalajara |
| Claudia   | Guadalajara | Scartlet  | Guadalajara |
| Scartlet  | Guadalajara | Scartlet  | Guadalajara |
| Sergio    | Guadalajara | Scartlet  | Guadalajara |
| Robert    | Guadalajara | Sergio    | Guadalajara |
| Manuel    | Guadalajara | Sergio    | Guadalajara |
| Dalia     | Guadalajara | Sergio    | Guadalajara |
| Alejandra | Guadalajara | Sergio    | Guadalajara |
| Luis      | Guadalajara | Sergio    | Guadalajara |
| Monica    | Guadalajara | Sergio    | Guadalajara |
| Claudia   | Guadalajara | Sergio    | Guadalajara |
| Scartlet  | Guadalajara | Sergio    | Guadalajara |
| Sergio    | Guadalajara | Sergio    | Guadalajara |
| Rick      | Mexico City | Rick      | Mexico City |
| Rene      | Mexico City | Rick      | Mexico City |
| Rick      | Mexico City | Rene      | Mexico City |
| Rene      | Mexico City | Rene      | Mexico City |
| Ramon     | Culiacan    | Ramon     | Culiacan    |
| Junior    | Culiacan    | Ramon     | Culiacan    |
| Kasandra  | Culiacan    | Ramon     | Culiacan    |
| Emma      | Culiacan    | Ramon     | Culiacan    |
| Ramon     | Culiacan    | Junior    | Culiacan    |
| Junior    | Culiacan    | Junior    | Culiacan    |
| Kasandra  | Culiacan    | Junior    | Culiacan    |
| Emma      | Culiacan    | Junior    | Culiacan    |
| Ramon     | Culiacan    | Kasandra  | Culiacan    |
| Junior    | Culiacan    | Kasandra  | Culiacan    |
| Kasandra  | Culiacan    | Kasandra  | Culiacan    |
| Emma      | Culiacan    | Kasandra  | Culiacan    |
| Ramon     | Culiacan    | Emma      | Culiacan    |
| Junior    | Culiacan    | Emma      | Culiacan    |
| Kasandra  | Culiacan    | Emma      | Culiacan    |
| Emma      | Culiacan    | Emma      | Culiacan    |
| Johnatha  | Dunedin     | Johnatha  | Dunedin     |
| Miriam    | Largo       | Miriam    | Largo       |
| Julie     | Largo       | Miriam    | Largo       |
| Miriam    | Largo       | Julie     | Largo       |
| Julie     | Largo       | Julie     | Largo       |
+-----------+-------------+-----------+-------------+

除了建议的解决方案之外,有人可以向我解释为什么我会得到这个结果吗?我想知道这是怎么发生的,为什么会这样。

谢谢。

您在位置上匹配,出现了多次。这与您当前的结果相乘。

您的预期结果是连接名称:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1, users users2
WHERE users1.name = users2.name;

查询的工作原理:

在数据集中,WHERE 中的列是匹配的。这相当于 JOIN:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1
INNER JOIN users users2 ON users1.name = users2.name;

这是现在比较常用的语法。这两个查询是相同的,但是使用 JOIN 后它变得更具可读性和灵活性。

JOIN 中的匹配是在 users1.name 等于 users2.name 时进行的。然后显示找到的结果:

| Robert | Guadalajara |

例如

如果查询是 运行,位置而不是名称:

INNER users users2 ON users1.location = users2.location;

SQL 匹配位置。因此,对于一个更短、更易读的例子,想象一下这个简短的 table。添加列 ID 以显示收集结果的方式:

+-----------+-------------+----+
| name      | location    | ID |
+-----------+-------------+----+
| Robert    | Guadalajara | 1  |
| Manuel    | Guadalajara | 2  |

这是在位置上匹配的,出现了两次:

Id 1 is matched with Id 1 and Id 2 (using location): Resulting in 2 records for location:

 | Robert    | Guadalajara | 1  |
 | Manuel    | Guadalajara | 1  |

Id 2 is matched with Id 1 and Id 2 (using location): Resulting in 2 records for location:

 | Robert    | Guadalajara | 2  |
 | Manuel    | Guadalajara | 2  |

所以最终结果将是:

| Robert    | Guadalajara | 1  |
| Manuel    | Guadalajara | 1  |
| Robert    | Guadalajara | 2  |
| Manuel    | Guadalajara | 2  |

因此您的原始记录成倍增加。

要获得您期望的结果,您需要在名称和位置上加入:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1
JOIN users users2 ON users1.location = users2.location 
                 AND users1.name = users2.name ;

在这个问题中,你说你想要一个结果匹配具有相同位置的人,如果是这样,那么你想要的是:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1
JOIN users users2 ON users1.location = users2.location 
                 AND users1.name <> users2.name ;

查看此 sample SQL Fiddle 以获得两个结果的示例

请注意,第二个查询将重复结果,因为每个匹配项都会有一个相应的对称匹配项(Robert 和 Luis 匹配项,还有 Luis 和 Robert)。我认为以下查询应该可以解决这个问题:

SELECT users1.name, users1.location, users2.name, users2.location
FROM users users1
JOIN users users2 ON users1.location = users2.location 
AND CASE WHEN users1.name < users2.name THEN users1.name ELSE users2.name END <> users2.name;

Sample SQL Fiddle 最后一个查询。