Choisissez parmi une table où pas dans une autre

J’essaie de trouver les lignes qui sont dans une table mais pas une autre, les deux tables sont dans des bases de données différentes et ont également des noms de colonne différents sur la colonne que j’utilise pour correspondre.

J’ai une requête, code ci-dessous, et je pense que ça marche probablement mais c’est trop lent:

SELECT `pm`.`id` FROM `R2R`.`partmaster` `pm` WHERE NOT EXISTS ( SELECT * FROM `wpsapi4`.`product_details` `pd` WHERE `pm`.`id` = `pd`.`part_num` ) 

La requête tente donc de faire comme suit:

Sélectionnez tous les identifiants de la firebase database R2R.partmaster qui ne figurent pas dans la firebase database wpsapi4.product_details. Les colonnes que je recherche sont partmaster.id & product_details.part_num

En développant l’anti-jointure de Sjoerd, vous pouvez également utiliser le modèle SELECT WHERE X NOT IN (SELECT) facile à comprendre.

 SELECT pm.id FROM r2r.partmaster pm WHERE pm.id NOT IN (SELECT pd.part_num FROM wpsapi4.product_details pd) 

Notez que vous n’avez besoin d’utiliser que des backticks sur les mots réservés, des noms avec des espaces et autres, pas avec des noms de colonnes normaux.

Sur MySQL 5+, ce type de requête est assez rapide.
Sur MySQL 3/4, c’est lent.

Assurez-vous d’avoir des index sur les champs en question
Vous devez avoir un index sur pm.id , pd.part_num .

Vous pouvez vous joindre aux deux tables. S’il n’y a pas de ligne correspondante dans la seconde table, les valeurs seront NULL.

 SELECT id FROM partmaster LEFT JOIN product_details ON (...) WHERE product_details.part_num IS NULL 

Donc, il y a beaucoup de publications sur le Web qui montrent comment faire cela, j’ai trouvé 3 façons, comme cela a été souligné par Johan & Sjoerd. Je ne pouvais faire fonctionner aucune de ces requêtes, bien évidemment, elles fonctionnent correctement, c’est que ma firebase database ne fonctionne pas correctement et que toutes les requêtes ont été lentes.

J’ai donc trouvé une autre solution utile pour quelqu’un d’autre:

Le principe de base consiste à créer une table temporaire et à la remplir avec toutes les informations, puis à supprimer toutes les lignes qui figurent dans l’autre table.

J’ai donc fait ces 3 requêtes et ça a fonctionné rapidement (dans quelques instants).

 CREATE TEMPORARY TABLE `database1`.`newRows` SELECT `t1`.`id` AS `columnID` FROM `database2`.`table` AS `t1` 

.

 CREATE INDEX `columnID` ON `database1`.`newRows`(`columnID`) 

.

 DELETE FROM `database1`.`newRows` WHERE EXISTS( SELECT `columnID` FROM `database1`.`product_details` WHERE `columnID`=`database1`.`newRows`.`columnID` ) 

Pour développer la réponse de Johan, si la colonne part_num de la sous-sélection peut contenir des valeurs nulles, la requête sera interrompue.

Pour corriger cela, ajoutez une vérification null …

 SELECT pm.id FROM r2r.partmaster pm WHERE pm.id NOT IN (SELECT pd.part_num FROM wpsapi4.product_details pd and pd.part_num is not null) 
  • Désolé mais je n’ai pas pu append de commentaire car je n’ai pas le représentant!