2013-05-09 4 views
3

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

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

..where конечно «$ струнной» является PHP переменная, содержащая разделенные запятыми значения только тех конфет, которые я хочу использовать, чтобы вытащить мальчиков.

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

EDIT:

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

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.

ответ

9

эта проблема называется 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 

UPDATE 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 
+0

+1 Великий ответ. Я думаю, вы должны взять предложение WHERE, чтобы вы не возвращали мальчиков, у которых есть * больше *, чем предметы в нужном списке. – Tom

+0

На самом деле это тоже не сработает. Я думаю, вам нужно будет добавить еще одно предложение HAVING, чтобы убедиться, что оно было просто нужным. 4. – Tom

+1

Проблема в том, что вы вернете всех мальчиков, у которых есть эти 4, есть ли у них дополнительные или нет. Вы должны удалить предложение WHERE и добавить второе предложение HAVING, чтобы избежать этого. Второе предложение HAVING может быть (в вашем примере): 'И COUNT (DISTINCT CASE WHEN chocolate_id IN (1,2,3,4) THEN chocolate_id ELSE NULL END) = 4'. – Tom