小编典典

如何在具有可传递性的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      |

我必须对这张表进行归一化处理。因此,我的第一个想法是尝试获取成对的相似注册表。像这样的东西:

| a.ID | b.ID | 
|   1  |  2   |
|   3  |  4   |
|   3  |  5   |

做一点实验:

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

这导致这样的问题:

| a.ID | b.ID | 
|   1  |  2   |
|   2  |  1   |
|   3  |  4   |
|   3  |  5   |
|   4  |  3   |
|   4  |  5   |
|   5  |  3   |
|   5  |  4   |

两对重复。

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

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

所以,我得到了这个:

| a.ID | b.ID | 
|   1  |  2   |
|   3  |  4   |
|   3  |  5   |
|   4  |  5   |

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


阅读 139

收藏
2021-04-28

共1个答案

小编典典

仅在一侧分组,然后在另一侧分组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

sqlfiddle上看到它。

2021-04-28