SQL – trouver des enregistrements d’une table qui n’existent pas dans une autre

J’ai les deux tables SQL suivantes (en MySQL):

Phone_book +----+------+--------------+ | id | name | phone_number | +----+------+--------------+ | 1 | John | 111111111111 | +----+------+--------------+ | 2 | Jane | 222222222222 | +----+------+--------------+ Call +----+------+--------------+ | id | date | phone_number | +----+------+--------------+ | 1 | 0945 | 111111111111 | +----+------+--------------+ | 2 | 0950 | 222222222222 | +----+------+--------------+ | 3 | 1045 | 333333333333 | +----+------+--------------+ 

Comment savoir quels appels ont été effectués par des personnes dont le phone_number ne figure pas dans le Phone_book ? La sortie souhaitée serait:

 Call +----+------+--------------+ | id | date | phone_number | +----+------+--------------+ | 3 | 1045 | 333333333333 | +----+------+--------------+ 

Toute aide serait très appréciée.

Il y a plusieurs façons de procéder, avec une efficacité variable, en fonction de la qualité de votre optimiseur de requête et de la taille relative de vos deux tables:

Ceci est la déclaration la plus courte et peut être plus rapide si votre annuaire est très court:

 SELECT * FROM Call WHERE phone_number NOT IN (SELECT phone_number FROM Phone_book) 

alternativement (grâce à Alterlife )

 SELECT * FROM Call WHERE NOT EXISTS (SELECT * FROM Phone_book WHERE Phone_book.phone_number = Call.phone_number) 

ou (grâce au WOPR)

 SELECT * FROM Call LEFT OUTER JOIN Phone_Book ON (Call.phone_number = Phone_book.phone_number) WHERE Phone_book.phone_number IS NULL 

(en ignorant cela, comme d’autres l’ont dit, il est normalement préférable de ne sélectionner que les colonnes que vous voulez, pas « * »)

 SELECT Call.ID, Call.date, Call.phone_number FROM Call LEFT OUTER JOIN Phone_Book ON (Call.phone_number=Phone_book.phone_number) WHERE Phone_book.phone_number IS NULL 

Devrait supprimer la sous-requête, permettant à l’optimiseur de requêtes de travailler sa magie.

De même, évitez “SELECT *” car il peut casser votre code si quelqu’un modifie les tables ou les vues sous-jacentes (et il est inefficace).

Le code ci-dessous serait un peu plus efficace que les réponses présentées ci-dessus pour traiter des ensembles de données plus importants.

 SELECT * FROM Call WHERE NOT EXISTS (SELECT 'x' FROM Phone_book where Phone_book.phone_number = Call.phone_number) 
 SELECT DISTINCT Call.id FROM Call LEFT OUTER JOIN Phone_book USING (id) WHERE Phone_book.id IS NULL 

Cela retournera les identifiants supplémentaires manquants dans votre table Phone_book.

je pense

 SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON CALL.id = Phone_book.id WHERE Phone_book.name IS NULL 
 SELECT t1.ColumnID, CASE WHEN NOT EXISTS( SELECT t2.FieldText FROM Table t2 WHERE t2.ColumnID = t1.ColumnID) THEN t1.FieldText ELSE t2.FieldText END FieldText FROM Table1 t1, Table2 t2 
 SELECT name, phone_number FROM Call a WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b) 

Alternativement,

 select id from call minus select id from phone_number