Существует некоторая неопределенность относительно того, хотите ли вы предотвратить вставку дубликатов в базу данных. Возможно, вы просто захотите получить уникальные пары, сохранив дубликаты.
Итак, вот альтернативное решение для последнего случая, запрашивающее уникальные пары, даже если существуют дубликаты:
SELECT r1.*
FROM Relationships r1
LEFT OUTER JOIN Relationships r2
ON (r1.person_1 = r2.person_2 AND r1.person_2 = r2.person_1)
WHERE r1.person_1 < r1.person_2
OR r2.person_1 IS NULL;
Так что, если есть совпадающая строка с обратным идентификатором, есть правило, для которого предпочтение должно быть выполнено запросом (правило с идентификаторами в числовом порядке).
Если соответствующей строки нет, то r2 будет NULL (так работает внешнее объединение), поэтому в этом случае просто используйте все, что найдено в r1.
Нет необходимости использовать GROUP BY
или DISTINCT
, потому что может быть только ноль или одна совпадающая строка.
Пробуя это в MySQL, я получаю следующий план оптимизации:
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------------+------+--------------------------+
| 1 | SIMPLE | r1 | ALL | NULL | NULL | NULL | NULL | 2 | |
| 1 | SIMPLE | r2 | eq_ref | PRIMARY | PRIMARY | 8 | test.r1.person_2,test.r1.person_1 | 1 | Using where; Using index |
+----+-------------+-------+--------+---------------+---------+---------+-----------------------------------+------+--------------------------+
Кажется, это разумно хорошее использование индексов.