MySQL: Выборка повторяющихся записей

Чтоб получить количество записей, в которых одно или несколько полей одинаковы, можно воспользоваться такой конструкцией:
SELECT `fhash_low`, `fhash_high`, COUNT( * ) `cnt`
FROM `mt_tfiles`
GROUP BY `fhash_low`, `fhash_high`
HAVING `cnt` > 1

В этом примере выборка количества записей, в которых одинаковые поля `fhash_low` , `fhash_high`(у меня так хранится MD5 хэш, разбитый на 2 длинных целых числа).
HAVING `cnt` > 1
Производит отсечение записей, в которых количество меньше или равно 1 – т.е. начиная от 2. Те, кто читал, что такое HAVING прекрасно понимают, что его использование нежелательно, особенно при больших результатах выборки(т.е. при отсутствии предложения WHERE или слишком мягких условиях)

Получение индексов повторяющихся полей

Если заведомо известно, что количество индексов повторяющихся строк не большое, то можно попробовать так:

SELECT `some_field`, COUNT( * ) `cnt`,
CAST( GROUP_CONCAT( `id` ) AS CHAR ) `ids`
FROM `table_name`
GROUP BY `some_field`
HAVING `cnt` >1

Т.е. добавляем поле ids, которое будет собой представлять строку из индексов, через запятую. Длина этой строки по дефолту – не более 1024 символа, большие будут урезаться. Этот параметр можно настроить в конфиге сервера базы данных. Переменная называется group_concat_max_len. Отсюда изначальное ограничение на количество повторяемых данных, вытаскиваемых таким способом.

Думаю очевидно, что такой подход приятнее. При выборки конечных записей, можно просто подставить … WHERE `id` IN ( {$row->ids} ) …, ну или программно разбить строку ids на массив по символу запятой.

Тайпкастинг CAST( … AS CHAR ) `ids` использовал исключительно для того, чтоб PhpMyAdmin показал не BLOB, а строку. Эту конструкцию можно безболезненно убрать при запросе из программы.