Как найти дубликаты в 2 столбцах не 1

У меня есть таблица базы данных MySQL с двумя столбцами, которые меня интересуют. Индивидуально они могут иметь дубликаты, но у них никогда не должно быть дубликатов ОБОИХ из них, имеющих одинаковое значение.

stone_id может иметь дубликаты, если для каждого заголовка upsharge другое значение, и наоборот. Но скажем, например, stone_id= 412 и upcharge_title= "sapphire", что комбинация должна выполняться только один раз.

Это нормально:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "ruby"

Это НЕ нормально:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "sapphire"

Есть ли запрос, который найдет дубликаты в обоих полях? И если возможно, есть ли способ установить, что моя база данных не позволяет этого?

Я использую MySQL версии 4.1.22

Ответ 1

Вы должны настроить составной ключ между двумя полями. Для каждой строки потребуется уникальное значение stone_id и upcharge_title.

Что касается поиска существующих дубликатов, попробуйте это:

select   stone_id,
         upcharge_title,
         count(*)
from     your_table
group by stone_id,
         upcharge_title
having   count(*) > 1

Ответ 2

Мне было полезно добавить индекс unqiue, используя "ALTER IGNORE", который удаляет дубликаты и применяет уникальные записи, которые звучат так, как вы хотели бы сделать. Таким образом, синтаксис будет выглядеть следующим образом:

ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);

Это эффективно добавляет уникальное ограничение, означающее, что у вас никогда не будет дубликатов записей, а IGNORE удаляет существующие дубликаты.

Подробнее о eh ALTER IGNORE вы можете узнать здесь: http://mediakey.dk/~cc/mysql-remove-duplicate-entries/

Обновление: мне было сообщено @Inquisitive, что это может быть неудачно в версиях MySql > 5.5:

Не удается выполнить команду MySQL > 5.5 и в таблице InnoDB, а в Percona из-за их функция быстрого индексирования InnoDB [http://bugs.mysql.com/bug.php?id=40344]. В этом случае сначала запустите set session old_alter_table=1, а затем указанную выше команду будет отлично работать

Ответ 3

Чтобы найти дубликаты:

select stone_id, upcharge_title from tablename group by stone_id, upcharge_title having count(*)>1

Чтобы ограничить это в будущем, создайте составной уникальный ключ в этих двух областях.

Ответ 4

Вы можете найти дубликаты, подобные этому.

Select
    stone_id, upcharge_title, count(*)
from 
    particulartable
group by 
    stone_id, upcharge_title
having 
    count(*) > 1

Ответ 5

Кстати, сложное уникальное ограничение в таблице помешало бы этому в первую очередь.

ALTER TABLE table
    ADD UNIQUE(stone_id, charge_title)

(Это действительный T-SQL. Не уверен в MySQL.)

Ответ 6

эта служба SO помогла мне, но я тоже хотел знать, как удалить и сохранить одну из строк... здесь PHP-решение для удаления повторяющихся строк и сохранения одного (в моем случае было всего 2 столбца, и это находится в функции для очистки дублирующих ассоциаций категорий)

$dupes = $db->query('select *, count(*) as NUM_DUPES from PRODUCT_CATEGORY_PRODUCT group by fkPRODUCT_CATEGORY_ID, fkPRODUCT_ID having count(*) > 1');
if (!is_array($dupes))
    return true;
foreach ($dupes as $dupe) {
    $db->query('delete from PRODUCT_CATEGORY_PRODUCT where fkPRODUCT_ID = ' . $dupe['fkPRODUCT_ID'] . ' and fkPRODUCT_CATEGORY_ID = ' . $dupe['fkPRODUCT_CATEGORY_ID'] . ' limit ' . ($dupe['NUM_DUPES'] - 1);
}

(ограничение NUM_DUPES - 1) является тем, что сохраняет одну строку...

спасибо всем