SELECT * FROM table1 t1 WHERE t1.champ1 NOT IN (SELECT champ2 FROM table2 t2)
edit : message supprimé par erreur par modérateur maladroit (avec toutes mes excuses) #
From MySQL 4.1 on, IN() syntax also is used to write certain types of subqueries. See Section 13.1.8.3, “Subqueries with ANY, IN, and SOME”.
#
expr NOT IN (value,...)
This is the same as NOT (expr IN (value,...)).
SELECT *
FROM table1 t1
WHERE t1.champ1 NOT IN (SELECT champ2
FROM table2 t2)
Mieux vaut :
SELECT *
FROM table1 t1 LEFT JOIN table2 t2 ON t1.champ1 = t2.champ2
WHERE t2.champ2 IS NULL
Cette requête est optimisée.
Pour le problème posé plus haut, la solution d'albat est exactement ce qu'il faut.Une clause LEFT [OUTER] JOIN peut être plus rapide qu'une sous-requête équivalent, car le serveur va pouvoir l'optimiser bien mieux : c'est un fait qui n'est pas spécifique à MySQL. Avant SQL-92, les jointures externes n'existaient pas, et les sous-requêtes étaient la seule méthode pour résoudre certains problèmes. Aujourd'hui, le serveur MySQL et d'autres bases de données modernes offrent toute une gamme de jointures externes.
Code : Tout sélectionner
SELECT *
FROM table1 t1
WHERE id NOT IN(
SELECT id FROM t2
WHERE t2.col3 (BETWEEN 'valeur1' AND 'valeur2')
AND t2.col4 <= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
)Code : Tout sélectionner
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
WHERE t2.col3 (BETWEEN 'valeur1' AND 'valeur2')
AND t2.col4 <= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
AND t2.id IS NULLCode : Tout sélectionner
# query 1: requête de précaution au cas où...
DROP TABLE IF EXISTS table_temp
# query 2: création de la table temporaire
CREATE TABLE table_temp
SELECT id
FROM table2 t2
WHERE
AND t2.col3 (BETWEEN 'valeur1' AND 'valeur2')
AND t2.col4 <= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
# query optionnelle: création d'un index temporaire pour accélérer la requête finale
# Très efficace. Je recommande chaudement!
ALTER TABLE table_temp ADD INDEX (col_a_indexer)
# query 3: exécution de la requête recherchée
SELECT *
FROM table1 t1
LEFT JOIN table_temp ON t1.id = table_temp.id
WHERE table_temp.id IS NULL
# query 4: suppression de la table temporaire
DROP table_temp// génération d'un nom de table temporaire aléatoire
$carAcceptes = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789';
$max = strlen($carAcceptes)-1;
$table_temp = 'temp_';
for($i=0; $i <= 4; $i++) {
$table_temp .= $carAcceptes{mt_rand(0, $max)};
}
Ne pas oublier le DROP TABLE du query 4 dans ce cas, sinon la base de données sera vite saturée!