web-dev-qa-db-fra.com

Comment sélectionner des lignes sans entrée correspondante dans une autre table?

J'effectue des travaux de maintenance sur une application de base de données et j'ai découvert que la joie des joies, même si les valeurs d'une table sont utilisées dans le style des clés étrangères, ne comporte aucune contrainte de clé étrangère.

J'essaie d'ajouter des contraintes FK sur ces colonnes, mais je constate que, parce qu'il y a déjà toute une charge de données erronées dans les tables d'erreurs précédentes qui ont été corrigées naïvement, il me faut trouver les lignes qui ne le sont pas. correspondre à l'autre table, puis supprimez-les.

J'ai trouvé quelques exemples de ce type de requête sur le Web, mais ils semblent tous fournir des exemples plutôt que des explications, et je ne comprends pas pourquoi elles fonctionnent.

Quelqu'un peut-il m'expliquer comment construire une requête qui renvoie toutes les lignes sans correspondance dans une autre table et ce qu'elle fait pour que je puisse effectuer ces requêtes moi-même, plutôt que de s'exécuter à SO pour chaque table dans ce mess qui n’a pas de contraintes FK?

238
Frosty840

Voici une requête simple:

SELECT t1.ID
FROM Table1 t1
    LEFT JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.ID IS NULL

Les points clés sont:

  1. LEFT JOIN est utilisé; cela renverra TOUTES les lignes de Table1, qu'il y ait ou non une ligne correspondante dans Table2.

  2. La clause WHERE t2.ID IS NULL; cela limitera les résultats renvoyés aux seules lignes où l'ID renvoyé par Table2 est null - autrement dit, il existeNOrecord dans Table2 pour cet ID particulier provenant de Table1. Table2.ID sera retourné comme NULL pour tous les enregistrements de Table1 où l'ID ne correspond pas dans Table2.

465
AdaTheDev

Je voudrais utiliser EXISTS expression car il est plus puissant, vous pouvez choisir plus précisément les lignes que vous souhaitez rejoindre, dans le cas où LEFT JOIN vous devez prendre tout ce qui est dans la table jointe. Son efficacité est probablement la même que dans le cas de LEFT JOIN avec test nul.

SELECT t1.ID
FROM Table1 t1
WHERE NOT EXISTS (SELECT t2.ID FROM Table2 t2 WHERE t1.ID = t2.ID)
45
Ondrej Bozek
SELECT id FROM table1 WHERE foreign_key_id_column NOT IN (SELECT id FROM table2)

Le tableau 1 contient une colonne à laquelle vous souhaitez ajouter la contrainte de clé étrangère, mais les valeurs du foreign_key_id_column ne correspondent pas toutes à une id du tableau 2.

  1. La sélection initiale répertorie les ids de table1. Ce seront les lignes que nous voulons supprimer. 
  2. La clause NOT IN de l'instruction where limite la requête aux seules lignes où la valeur de foreign_key_id_column ne figure pas dans la liste de la table 2 ids. 
  3. La déclaration SELECT entre parenthèses obtiendra une liste de tous les ids du tableau 2.
9
Theo Voss

T2 est la table à laquelle vous ajoutez la contrainte:

SELECT *
FROM T2
WHERE constrained_field NOT
IN (
    SELECT DISTINCT t.constrained_field
    FROM T2 
    INNER JOIN T1 t
    USING ( constrained_field )
)

Et supprimez les résultats.

7
Karel

Ayons les 2 tables suivantes (salaire et employé)  enter image description here

Maintenant, je veux les enregistrements de la table employee qui ne sont pas en salaire. Nous pouvons le faire de 3 façons-

  1. Utilisation de la jointure interne

    sélectionnez * auprès de l'employé sans identifiant (sélectionnez e.id dans le salaire de l'employé)

 enter image description here

  1. Utilisation de la jointure externe gauche 

    sélectionnez * auprès de l'employé e quitté le salaire de jointure externe s sur e.id = s.id où s.id est null

 enter image description here

  1. Utilisation de la jointure complète

    sélectionnez * parmi l'employé et le salaire total des membres externes sur e.id = s.id, où e.id n'est pas inclus

 enter image description here

2
Debendra Dash

De la même question ici MySQL Inner Join Query Pour obtenir des enregistrements non présents dans une autre table

SELECT * FROM bigtable 
LEFT JOIN smalltable ON bigtable.id = smalltable.id 
WHERE smalltable.id IS NULL

smalltable est l'endroit où vous avez des enregistrements manquants, bigtable est l'endroit où vous avez tous les enregistrements. La requête répertorie tous les enregistrements qui n'existent pas dans smalltable mais existent sur bigtable. Vous pouvez remplacer id par n’importe quel autre critère correspondant.

1
Luis H Cabrejo

Vous pouvez opter pour Vues comme indiqué ci-dessous:

CREATE VIEW AuthorizedUserProjectView AS select t1.username as username, t1.email as useremail, p.id as projectid, 
(select m.role from userproject m where m.projectid = p.id and m.userid = t1.id) as role 
FROM authorizeduser as t1, project as p

puis travaillez sur la vue pour sélectionner ou mettre à jour:

select * from AuthorizedUserProjectView where projectid = 49

qui donne le résultat comme indiqué dans l’illustration ci-dessous, c’est-à-dire que la colonne non correspondante a la valeur null.

[Result of select on the view][1]
0
Nitesh singh