2013-07-13 3 views
3

я столкнулся с очень плохо разработанную базу данных с ненормированным таблицы X. Эта таблица X должна иметь N: M отношения с другой таблицей Y.Как выбрать отдельные пары в MySQL join (та же таблица) с транзитивностью?

Проблема заключается в том, что эти отношения в настоящее время 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 | 

Но мне еще нужно, чтобы избавиться от этого последнего регистра.

ответ

7

Группы только с одной стороны и принять 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.

+0

Да, это просто! Я должен подождать еще шесть минут, чтобы принять этот ответ ... –

+0

Кстати, спасибо = D –

+0

Можете ли вы объяснить, как работает этот запрос? ти – themis