102 votes

MySQL Rejoindre Où N'existe Pas

J'ai une requête MySQL qui joint deux tables

  • Électeurs
  • Ménages

Elles sont jointes sur voters.household_id et household.id.

Maintenant, ce que je dois faire, c'est la modifier pour que la table des électeurs soit jointe à une troisième table appelée elimination, le long de voter.id et elimination.voter_id. Cependant, la particularité est que je veux exclure tout enregistrement dans la table des électeurs qui a un enregistrement correspondant dans la table elimination.

Comment puis-je concevoir une requête pour cela ?

Voici ma requête actuelle :

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`,
       `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`,
       `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`,
       `household`.`Address`, `household`.`City`, `household`.`Zip`
FROM (`voter`)
JOIN `household` ON `voter`.`House_ID`=`household`.`id`
WHERE `CT` = '5'
AND `Precnum` = 'CTY3'
AND  `Last_Name`  LIKE '%Cumbee%'
AND  `First_Name`  LIKE '%John%'
ORDER BY `Last_Name` ASC
LIMIT 30

251voto

NickZoic Points 2406

Je utiliserais probablement un LEFT JOIN, qui retournera des lignes même s'il n'y a pas de correspondance, puis vous pouvez choisir uniquement les lignes sans correspondance en vérifiant les NULLs.

Donc, quelque chose comme:

SELECT V.*
FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id
WHERE E.voter_id IS NULL

Que ce soit plus ou moins efficace que d'utiliser une sous-requête dépend de l'optimisation, des index, s'il est possible d'avoir plus d'une élimination par votant, etc.

11voto

Ian Clelland Points 15066

Je vais utiliser un 'where not exists' -- exactement comme vous le suggérez dans votre titre:

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`,
       `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`,
       `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`,
       `household`.`Address`, `household`.`City`, `household`.`Zip`
FROM (`voter`)
JOIN `household` ON `voter`.`House_ID`=`household`.`id`
WHERE `CT` = '5'
AND `Precnum` = 'CTY3'
AND  `Last_Name`  LIKE '%Cumbee%'
AND  `First_Name`  LIKE '%John%'

AND NOT EXISTS (
  SELECT * FROM `elimination`
   WHERE `elimination`.`voter_id` = `voter`.`ID`
)

ORDER BY `Last_Name` ASC
LIMIT 30

Cela peut être marginalement plus rapide que de faire une jointure externe (bien sûr, en fonction de vos index, cardinalité de vos tables, etc), et est presque certainement beaucoup plus rapide que d'utiliser IN.

9voto

Il existe trois façons possibles de le faire.

  1. Option

    SELECT  lt.* FROM    table_left lt
    LEFT JOIN
        table_right rt
    ON      rt.value = lt.value
    WHERE   rt.value IS NULL
  2. Option

    SELECT  lt.* FROM    table_left lt
    WHERE   lt.value NOT IN
    (
    SELECT  value
    FROM    table_right rt
    )
  3. Option

    SELECT  lt.* FROM    table_left lt
    WHERE   NOT EXISTS
    (
    SELECT  NULL
    FROM    table_right rt
    WHERE   rt.value = lt.value
    )

6voto

Jose Basilio Points 29215

Essayez d'ajouter ce qui suit à votre clause WHERE :

ET `voter`.`id` NON DANS (SELECT `voter_id` DE (`elimination`))

5voto

vaychick Points 659

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X