2011-01-12 3 views
3

У меня проблема с поиском дублирующих результатов в базе данных mysql (сайт рецептов коктейлей). Здесь установка:Проблема с MySQL Query (повторяющиеся результаты)

Таблица 1: 'коктейль'
[чид, c_name] (CID = Уникальный коктейль ID, c_name = имя коктейль)

Таблица 2: 'ингредиенты':
[IID, i_name ] (IID = уникальный ингредиент ID, i_name = имя ингредиента)

Таблица 3: 'cocktail_ingredients' (связующая таблица)
[ciid, чид, IID] (ciid = уникальный идентификатор строки, чид = коктейль чид, IID = ингредиент iid)

Итак, один коктейль может иметь несколько строк в таблице «cocktail_ingredients» (от 1 до многих).

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

Например, если таблица cocktail_ingredients были эти записи:

ИДС | iid
1 | 56
1 | 78
1 | 101
. . .
9 | 56
9 | 78
9 | 101

Коктейль такой же (для теоретических целей здесь все равно).

Если в таблице 'cocktail_ingredients' был еще один ряд ...

9 | 103

Тогда это будет не то же самое, что и коктейль номер 9 включает в себя дополнительный ингредиент.

Таким образом, mysql должен выполнить 2 проверки, во-первых, что количество ингредиентов одинаковое, а во-вторых, каждый идентификатор ингредиента (iid) одинаковый для соответствующих коктейлей (cid).

Im тупик на этом, любая помощь очень ценится. Я думаю, что мне, возможно, придется идти по пути PHP, а также кодировать что-то более сложное, но я боюсь там, поэтому подумал, что это будет хорошее место, чтобы остановиться и спросить.

Спасибо тонных

Ник

+0

Только потому, что два коктейля содержат одни и те же ингредиенты, они не обязательно являются одним и тем же коктейлем. Количества могут различаться. –

+1

Да, я понимаю это - вот почему я сказал «для теоретических целей». Очевидно, способ, которым вы смешиваете, суммы и множество других переменных может изменить его. Но это, безусловно, дает мне хорошую базу, чтобы начать смотреть. –

ответ

1

Вы можете вспомнить из далекого математического класса, что определение множества равенства является то, что оба А абд B является подмножествами друга друга (нестрогим) так просто создать просмотр или процедура, которая проверяет, находится ли каждый тон, находящийся в A, также в B, тогда проверьте, что два коктейля являются обе подмножествами друг друга. Это далеко не полный ответ, но этого может быть достаточно, чтобы вы могли;)

, вероятно, будет легче сделать отрицание - найдите ингредиент в A, который не находится в B.не существует, то A должно быть строгим подмножеством B (при условии, что A и B не могут быть пустыми)

В качестве альтернативы, подсчитывайте каждый ингредиент в A, каждый ингредиент иона B и каждый ингредиент в A и B затем если они равны, они являются эквивалентными коктейлями

CREATE VIEW ingredient_count AS 
SELECT cid, count(*) as ingredients 
FROM cocktail_ingredients 
GROUP BY cid 

CREATE VIEW shared_ingredients AS 
SELECT c1.cid cid1, c2.cid cid2, count(*) as ingredients 
FROM cocktail_ingredients as c1 INNER JOIN cocktail_ingredients as c2 
ON (c1.cid != c2.cid AND c1.iid = c2.iid) 
GROUP BY c1.cid,c2.cid 

CREATE VIEW duplicates AS 
SELECT cid1,cid2 
FROM (ingredient_count AS ic1 INNER JOIN shared_ingredients 
     ON ic1.cid=cid1) INNER JOIN ingredient_count as ic2 
    ON ic2.cid=cid2 
WHERE ic1.ingredients=ic2.ingredients 
AND shared_ingredients=ic1.ingredients 

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

+0

Спасибо, тонна, хорошо выглядит, и мои воспоминания о классе Math медленно возвращаются ко мне. Я пойду позже, скрестив пальцы. –

+0

Я думаю, что это работает, но способ замедлить размер моей базы данных (таблица коктейлей держит 3000 записей, cocktail_ingredients держится более 12000, а ингредиенты занимают около 650). Я работаю над PHP-решением, но опять-таки его сложно. –

+0

@ Ник, см. Мою заметку внизу - вы сможете ускорить это, используя подзапросы вместо представлений (с соответствующими предложениями), я написал, что для читаемости не скорость. По моему опыту такой запрос может идти от 30 секунд до небольшой доли секунды, если все сделано правильно. – tobyodavies

-1

Вы можете наложить такие проверки с помощью TRIGGER , Но все же есть концептуальная проблема.

Скажите, у вас есть два коктейля {1 | 56, 78, 101} и {9 | 56, 78, 101, 103}, а также предположите, что вы внедрили чек.

Теперь вы вставляете данные 1:

cid | iid 
---------- 
1 | 56 

Затем добавьте два компонента отдыха ...

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 

Хорошо, теперь вы начинаете добавлять 9:

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 
9 | 56 

У вас есть еще три ингредиента, поэтому продолжайте добавлять их:

cid | iid 
---------- 
1 | 56 
1 | 78 
1 | 101 
9 | 56 
9 | 78 

Два других оставшихся (101,103) Но, увы! Вы не можете добавить 101! Если вы попытаетесь добавить 101, тогда 9 станет идентичным 1, что ваш триггер не позволит вам добавлять.

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

Вы не должны вводить никаких ограничений в базу данных. Что я буду делать в моем веб-приложения:

  1. В интерфейсе входа коктейль/обновление, я бы пользовательский ввод (и еще не вставки/обновления в БД)

  2. Когда пользователь нажимает кнопку сохранения (я бы добавил кнопку сохранения), проверьте, станет ли новый/обновленный коктейль копией другого (может быть, я бы написал хранимую процедуру, но ее можно найти, используя только выбранный запрос)

  3. Если новый/обновленный коктейль не дублирует другую, вставляет/обновляет базу данных. Если

+0

-1 Вы не должны вводить никаких ограничений в базу данных - это худший совет, который я когда-либо слышал. – tobyodavies

+0

Его нет для ограничений на добавление, просто для очистки существующих записей. Я могу добавить какое-то уведомление о том, что оно может быть одинаковым, но не остановит его по умолчанию. –

+0

@tobyodevis: PLZ прочитать ответ entie. вы обнаружите, что я сказал, что ограничение db может быть реализовано. но, в конце концов, я предложил что-то еще. В любом случае, использование триггера - очень распространенная практика oracle dba's. хотя его самое худшее, что вы слышали –