Эквивалентное предложение MySQL ONLY IN()

Я даю здесь очень абстрактную версию моего вопроса, поэтому, пожалуйста, потерпите меня. У меня есть запрос, который будет проверять, имеет ли конкретное тело несколько параметров одного типа. Например, мальчик имеет множественный выбор в отношении шоколада. Но я хочу выбрать мальчиков со стола, у которых есть именно те конфеты, о которых я упоминаю. Не больше и не меньше, а не «НРАВИТСЯ» или «IN()».

SELECT boy_id from boys_chocolates WHERE chocolate_id ONLY IN('$string');

..где, конечно, '$string' - это PHP-переменная, содержащая разделенные запятыми значения только тех конфет, которые я хочу использовать, чтобы тянуть мальчиков.

Я знаю, что это недопустимый оператор MySQL, но есть ли какой-либо действительный эквивалент этому?

РЕДАКТИРОВАТЬ:

Это более полный запрос, который получает записи в особых случаях, но не всегда.

SELECT boys.* FROM schools_boys INNER JOIN boys ON boys.boy_id=schools_boys.boy_id
INNER JOIN chocolates_boys a ON a.boy_id=boys.boy_id INNER JOIN schools
ON schools.school_id=schools_boys.school_id WHERE a.chocolate_id IN(1000,1003)
AND 
            EXISTS
            (
                    SELECT 1
                    FROM chocolates_boys b
                    WHERE a.boy_id=b.boy_id
                    GROUP BY boy_id
                    HAVING COUNT(DISTINCT chocolate_id) = '2'
                    )

                GROUP BY schools_boys.boy_id HAVING COUNT(*) = '2'

Boys Table
+--------+-------------+
| id     | boy         |
+--------+-------------+
| 10007  | Boy1        |
| 10008  | Boy2        |
| 10009  | Boy3        |
+--------+-------------+

Chocolates Boys Table
+----+---------+--------------+
| id | chocolate_id | boy_id |
+----+--------------+---------+
| 1  | 1000         | 10007   |
| 2  | 1003         | 10007   |
| 3  | 1006         | 10007   |
| 4  | 1000         | 10009   |
| 5  | 1001         | 10009   |
| 6  | 1005         | 10009   |
+----+--------------+---------+

Ничего не происходит, когда я выбираю только 1000, чтобы вытащить двух мальчиков (или) 1000 и 1003, чтобы вытащить мальчика с ID 10007.


person Vijay Kumar Kanta    schedule 09.05.2013    source источник


Ответы (1)


эта проблема называется Relational Division

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN ('$string')
GROUP  BY boy_id 
HAVING COUNT(DISTINCT chocolate_id) = ? -- <<== number of chocolates specified

пример:

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN (1,2,3,4)
GROUP  BY boy_id 
HAVING COUNT(DISTINCT chocolate_id) = 4

однако, если chocolate_id уникален для каждого ключевого слова boy_id, DISTINCT является необязательным.

SELECT boy_id 
FROM   boys_chocolates 
WHERE  chocolate_id IN (1,2,3,4)
GROUP  BY boy_id 
HAVING COUNT(*) = 4

ОБНОВЛЕНИЕ 1

...Я хочу выбрать мальчиков со стола, у которых есть именно те конфеты, о которых я упоминаю. Не больше не меньше...

SELECT boy_id 
FROM   boys_chocolates a
WHERE  chocolate_id IN (1,2,3,4) AND
        EXISTS 
        (
            SELECT  1
            FROM    boys_chocolates b
            WHERE   a.boy_ID = b.boy_ID
            GROUP   BY boy_id
            HAVING  COUNT(DISTINCT chocolate_id) = 4
        )
GROUP  BY boy_id
HAVING COUNT(*) = 4
person John Woo    schedule 09.05.2013
comment
+1 Отличный ответ. Я думаю, вам следует убрать предложение WHERE, чтобы вы не возвращали мальчиков, у которых больше, чем элементов в желаемом списке. - person Tom; 09.05.2013
comment
На самом деле это тоже не сработает. Я думаю, вам нужно будет добавить еще одно предложение HAVING, чтобы убедиться, что это именно то, что нужно 4. - person Tom; 09.05.2013
comment
Проблема в том, что вы вернете всех мальчиков, у которых есть эти 4, независимо от того, есть ли у них дополнительные или нет. Вы должны удалить предложение WHERE и добавить второе предложение HAVING, чтобы избежать этого. Второе предложение HAVING может быть (в вашем примере): AND COUNT(DISTINCT CASE WHEN chocolate_id IN (1,2,3,4) THEN chocolate_id ELSE NULL END) = 4. - person Tom; 09.05.2013
comment
@ Том, хорошая мысль, я неправильно прочитал эту строку: ...exactly the chocolates I mention. Простите, я обновлю ответ. - person John Woo; 09.05.2013
comment
Без проблем. Это был отличный ответ. Просто упустил один момент. - person Tom; 09.05.2013
comment
Я не могу использовать ваш ответ, потому что я соединяю 3 или более таблиц в одном запросе, а предложение FROM указывает на третью таблицу. Есть ли способ, которым мне не нужно приносить какие-либо данные из таблицы boys_chocolates и, конечно же, не нужно использовать предложение «FROM» в той же таблице? - person Vijay Kumar Kanta; 10.05.2013
comment
@ Том, я попробовал твою дополнительную причину HAVING, и это не сработало, как ожидалось. - person Vijay Kumar Kanta; 10.05.2013
comment
@Viz - Вы сначала удалили предложение WHERE? Также вам понадобится предложение HAVING для предложенного JW. Это будет выглядеть так: HAVING COUNT(DISTINCT chocolate_id) = 4 AND COUNT(DISTINCT CASE WHEN chocolate_id IN (1,2,3,4) THEN chocolate_id ELSE NULL END) = 4. - person Tom; 10.05.2013
comment
Если это не сработает, вам нужно опубликовать свои структуры таблиц и/или запрос, объединяющий таблицы, чтобы у нас было лучшее представление о том, что происходит. Очевидно, что это не так просто, как запрос, который вы разместили. - person Tom; 10.05.2013
comment
Да, это сработало для одного набора конфет, но не сработало для других наборов. Странный. - person Vijay Kumar Kanta; 29.05.2013
comment
Я отредактировал вопрос, добавив более подробный запрос, который является копией исходного запроса. - person Vijay Kumar Kanta; 01.06.2013
comment
Можете ли вы дать мне образцы записей, в которых запрос не дает правильного результата? - person John Woo; 01.06.2013
comment
Небольшое обновление, теперь после некоторых изменений я не получаю результатов ни для одной коллекции. Запрос точно такой же, как отредактированный запрос. проблема в том, что запрос, который я пишу, не совсем для мальчиков и шоколада. :п - person Vijay Kumar Kanta; 01.06.2013
comment
См. этот вопрос, чтобы понять, что я имею в виду под примерами записей с желаемыми результат Запрос, который я вам дал, работает с моим собственным набором данных. Поскольку у вас это не совсем работает, не могли бы вы дать мне набор ваших собственных данных? - person John Woo; 01.06.2013
comment
Пожалуйста, проверьте вопрос еще раз. Я привел реальные записи из моей базы данных. - person Vijay Kumar Kanta; 01.06.2013
comment
запрос можно упростить, удалив предложение exists, но это нарушит эту часть ...But, I want to choose boys from the table who have exactly the chocolates I mention. Not more not less and not 'LIKE' or not 'IN()'. - person John Woo; 01.06.2013
comment
Это работает в ссылке, которую вы мне дали, к сожалению, не на моем компьютере, на котором есть точный запрос с еще несколькими соединенными таблицами. На самом деле, если я выберу 1000 и 1003, появится человек с 1000 и 1005. - person Vijay Kumar Kanta; 01.06.2013
comment
Я хочу добавить, что когда я меняю номер счетчика вручную, я получаю разные результаты. Одна странная вещь, когда я просто выбираю 1000, а количество равно 1, я получаю только первого мальчика, затем я меняю количество на 2 вручную, теперь я получаю только второго мальчика. Итак, Результат всегда 1 мальчик. - person Vijay Kumar Kanta; 01.06.2013