如何在MySQL连接(同一个表)中选择具有传递性的不同对?

Hen*_*los 4 mysql sql

我面临着一个设计非常糟糕的数据库,其中包含一个非规范化的表X.这个表X应该与另一个表Y具有N:M的关系.

问题在于,这种关系目前是1:N,而且直到现在这个简单的操作解决方案是在有各种注册表相关时复制条目.

简化,我有这个:

| ID | TEXT | LOCATION_ID |
| 1  | foo  |      1      |
| 2  | foo  |      2      |
| 3  | bar  |      1      |
| 4  | bar  |      4      |
| 5  | bar  |      3      |
Run Code Online (Sandbox Code Playgroud)

我必须将此表标准化.所以,我的第一个想法是尝试获得成对的类似注册表.像这样的东西:

| a.ID | b.ID | 
|   1  |  2   |
|   3  |  4   |
|   3  |  5   |
Run Code Online (Sandbox Code Playgroud)

尝试一下:

SELECT a.id, b.id 
FROM mytable AS a 
INNER JOIN mytable AS b 
   ON a.text = b.text AND a.id != b.id 
GROUP BY a.id, b.id
Run Code Online (Sandbox Code Playgroud)

这导致了这样的问题:

| a.ID | b.ID | 
|   1  |  2   |
|   2  |  1   |
|   3  |  4   |
|   3  |  5   |
|   4  |  3   |
|   4  |  5   |
|   5  |  3   |
|   5  |  4   |
Run Code Online (Sandbox Code Playgroud)

这对是重复的.

经过一番挖掘,我意识到这更有效:

SELECT a.id, b.id 
FROM mytable AS a 
INNER JOIN mytable AS b 
        ON a.text = b.text AND a.id < b.id 
GROUP BY a.id, b.id
Run Code Online (Sandbox Code Playgroud)

所以,我得到了这个:

| a.ID | b.ID | 
|   1  |  2   |
|   3  |  4   |
|   3  |  5   |
|   4  |  5   |
Run Code Online (Sandbox Code Playgroud)

但我仍然需要摆脱最后一个寄存器.

egg*_*yal 8

仅在一侧进行分组并从另一侧进行分组MIN():

SELECT   MIN(a.ID) a, b.ID b
FROM     mytable a JOIN mytable b ON b.text = a.text AND b.ID > a.ID
GROUP BY b.ID
Run Code Online (Sandbox Code Playgroud)

sqlfiddle上看到它.