内部连接后自连接

self join after an inner join

我正在查找哪些城市在不同的州具有相同的名称。城市名称和州名称位于单独的 table 中(城市和州),并且可以通过单独的公共列进行内部连接。

select c1.city, c1.state, c2.city, c2.state 
from cities 
inner join states on cities.commonid = states.commonid

内部加入后我需要自我加入以执行如下功能

select c1.city, c1.state, c2.city, c2.state
from *joined table* c1 join
     *joined table* c2
     on c1.city = c2.city and c1.state <> c2.state

我想知道如何自己加入一个 table 这是同一查询中另一个加入的结果 输出将是这样的

+----------+-------+--------+--------+
| city1    | state1|city2   |state2  |
+----------+-------+--------+--------+
| x        | melb  | x      | syd    |
| y        | bris  | y      | ACT    |
+----------+-------+--------+--------+

您可以对内部联接查询执行 select 并为其指定别名。

然后就会变成下面这个样子...

Select c.city,c.state from
(Select City,state from cities inner join states where cities.id = states.id) as c

现在为 c 创建一个自连接。

我将对拥有多个州的所有城市执行预查询。然后加入状态table,看看他们遇到了哪些状态。

    select
          Duplicates.city,
          s.state
       from
          ( select c1.city
               from cities c1
               group by c1.city
               having count(*) > 1 ) Duplicates
             JOIN cities c2
                on Duplicates.city = c2.city
                JOIN states s
                   on c2.commonid = s.commonid
      order by
         Duplicates.city,
         s.state

如果不尝试只对两个 city/states 进行交叉制表,您将得到一个列表。如果一个城市名称存在于 5 个州,您打算如何显示它。这样你会看到所有按字母顺序排列的。

我假设 table cities 有一个像 state_id 这样的列引用了 table states 中的一个列 state_id (将名称更改为列的实际名称)。
首先为 cities 进行自连接,条件为:

c1.city = c2.city AND c1.state_id < c2.state_id

< 运算符确保每对城市只返回一次。
然后加入2份states,因为每一份都会被用来获取2个城市各自的州名:

SELECT c1.city city1, s1.state state1,
       c2.city city2, s2.state state2
FROM cities c1 
INNER JOIN cities c2 ON c1.city = c2.city AND c1.state_id < c2.state_id
INNER JOIN states s1 ON s1.state_id = c1.state_id
INNER JOIN states s2 ON s2.state_id = c2.state_id
ORDER BY city1

我建议 CTE:

with cs as (
      select c.name as city_name, s.name as state_name
      from cities c join
           states s
           on c.commonid = s.commonid
     )
select cs1.*, cs2.*
from cs cs1 join
     cs cs2
     on cs1.name = cs2.name and cs1.state <> cs2.state;