Prenons le cas de test suivant:
CREATE TABLE accounts (id int);
CREATE TABLE emails (id int, account_id int, type_name varchar(10), order_id int);
INSERT INTO accounts VALUES (1), (2), (3), (4);
INSERT INTO emails VALUES (1, 1, 'name', 1);
INSERT INTO emails VALUES (2, 1, 'no-name', 1);
INSERT INTO emails VALUES (3, 2, 'name', 1);
INSERT INTO emails VALUES (4, 2, 'no-name', 1);
INSERT INTO emails VALUES (5, 3, 'name', 2);
Ensuite, cela fonctionne comme prévu:
SELECT * FROM `accounts`
LEFT OUTER JOIN `emails` ON emails.account_id = accounts.id
WHERE (emails.type_name = 'name' AND emails.order_id = 1);
+------+------+------------+-----------+----------+
| id | id | account_id | type_name | order_id |
+------+------+------------+-----------+----------+
| 1 | 1 | 1 | name | 1 |
| 2 | 3 | 2 | name | 1 |
+------+------+------------+-----------+----------+
2 rows in set (0.00 sec)
Le problème avec votre deuxième requête est qu'il peut renvoyer une NULL
ligne s'il y a un compte pas de courriel, comme c'est le cas du numéro de compte 4:
SELECT * FROM `accounts`
LEFT OUTER JOIN `emails` ON emails.account_id = accounts.id
WHERE (!(emails.type_name = 'name' AND emails.order_id = 1) OR emails.id IS NULL);
+------+------+------------+-----------+----------+
| id | id | account_id | type_name | order_id |
+------+------+------------+-----------+----------+
| 1 | 2 | 1 | no-name | 1 |
| 2 | 4 | 2 | no-name | 1 |
| 3 | 5 | 3 | name | 2 |
| 4 | NULL | NULL | NULL | NULL |
+------+------+------------+-----------+----------+
4 rows in set (0.01 sec)
Pourquoi pas ce suffisant pour un résultat mutuellement exclusif fixé sans NULL
lignes ?:
SELECT * FROM `accounts`
LEFT OUTER JOIN `emails` ON emails.account_id = accounts.id
WHERE NOT (emails.type_name = 'name' AND emails.order_id = 1)
+------+------+------------+-----------+----------+
| id | id | account_id | type_name | order_id |
+------+------+------------+-----------+----------+
| 1 | 2 | 1 | no-name | 1 |
| 2 | 4 | 2 | no-name | 1 |
| 3 | 5 | 3 | name | 2 |
+------+------+------------+-----------+----------+
3 rows in set (0.00 sec)
Merci pour la réponse détaillée! Pour la deuxième requête, je recherche des comptes qui n'ont pas un certain type d'enregistrement de courrier électronique (type_name = 'name' AND order_id = 1). Dans votre exemple, les comptes 1 et 2 ont ce type d'enregistrement de courrier électronique, donc je ne veux pas que ceux-ci soient renvoyés. Compte 3 a un enregistrement d'email qui ne correspond pas, donc je veux que cela renvoyé. Le compte 4 n'a aucun enregistrement de courrier électronique, donc je veux que ce soit retourné parce qu'il ne peut pas correspondre. En résumé: Ma requête renvoie actuellement les comptes 1, 2, 3 et 4. Je ne veux que renvoyer 3 et 4. – tassock