I'm used to delete rows using joins in combination with "IS NULL", like this
Person A has number 1 of type 1. Person B has numer 2 of type 2, but also have number 1 of type 1.
SELECT people.name,
GROUP_CONCAT(phone_numbers.phone_number) AS "All number",
GROUP_CONCAT(IF(phone_numbers.type_id = 2, phone_numbers.phone_number, NULL)) AS "Type 2 Numbers"
FROM people
LEFT JOIN people_phones USING (people_id)
LEFT JOIN phone_numbers USING (phone_number)
GROUP BY people_id;
+------+------------+----------------+
| name | All number | Type 2 Numbers |
+------+------------+----------------+
| A | 1 | NULL |
| B | 1,2 | 2 |
+------+------------+----------------+
I want to remove all persons that don't have a type 2 number, in this case Person A.
First i tried the usal way (that works if its one join away)
DELETE people
FROM people
LEFT JOIN people_phones USING (people_id)
LEFT JOIN phone_numbers
ON (phone_numbers.phone_number = people_phones.phone_number
AND phone_numbers.type_id = 2)
WHERE phone_numbers.phone_number IS NULL;
but that removes both Person 'A' and Person 'B' as 'B' has a number that isn't type 2.
How do i remove people that don't have a type 2 number?
(The real exemple have more joins, and more complex where parts, and 5 miljon rows in the tables.)
CREATE TABLE people (people_id INT NOT NULL AUTO_INCREMENT KEY, name TINYTEXT NOT NULL);
CREATE TABLE phone_numbers (phone_number INT NOT NULL KEY, type_id INT NOT NULL);
CREATE TABLE people_phones (people_id INT NOT NULL, phone_number INT NOT NULL, PRIMARY KEY(people_id, phone_number))
INSERT INTO people VALUES (1,'A'),(2,'B');
INSERT INTO phone_numbers VALUES (1, 1), (2,2);
INSERT INTO people_phones VALUES (1,1), (2,1), (2,2);
This is one way:
DELETE p
FROM people AS p
WHERE p.people_id NOT IN (SELECT pp.people_id
FROM people_phones as pp
INNER JOIN phone_numbers as pn
ON pp.phone_number = pn.phone_number
WHERE pn.type_id = 2);
And another way:
DELETE p
FROM people AS p
WHERE NOT EXISTS(SELECT 1
FROM people_phones as pp
INNER JOIN phone_numbers as pn
ON pp.phone_number = pn.phone_number
WHERE pn.type_id = 2
AND pp.people_id = p.people_id);
Here is a sqlfiddle with a demo of the second version (which is also the one that I recommend).