Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL ONLY IN() equivalent clause

I am giving a very abstract version of my question here, so please bear with me. I have a query that will check whether a particular body has certain multiple parameters of same type. Example, a boy has multiple selection as far as chocolates are concerned. 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()'.

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

..where of course '$string' is a PHP variable containing comma separated values of only those chocolates I want to use to pull the boys.

I know this is invalid MySQL statement, but is there any valid equivalent to this?

EDIT:

This is more comprehensive query which gets records in special cases, but not always.

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

Nothing happens when I select 1000 alone to pull two boys (or) 1000 and 1003 to pull out the boy with ID 10007.

like image 783
Vijay Kumar Kanta Avatar asked May 09 '13 12:05

Vijay Kumar Kanta


1 Answers

this problem is called 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

example:

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

however, if the chocolate_id is unique for every boy_id, DISTINCT keyword is optional.

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

UPDATE 1

...I want to choose boys from the table who have exactly the chocolates I mention. Not more not less...

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
  • SQLFiddle Demo
like image 103
John Woo Avatar answered Oct 17 '22 17:10

John Woo