not left inner mysql join not-exists

left - MySQL Unirse donde no existe



not in mysql subquery (4)

Tengo una consulta MySQL que une dos tablas

  • Votantes
  • Hogares a los que se unen votantes.household_id y household.id

    Ahora lo que tengo que hacer es modificarlo donde la tabla de votantes se une a una tercera tabla llamada eliminación, a lo largo de voter.id y eliminación.voter_id, ¿cómo es que la captura es que quiero excluir cualquier registro en la tabla de votantes que tienen un registro correspondiente en la tabla de eliminación. ¿Cómo hago una consulta para hacer esto?

esta es mi consulta actual

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


Hay tres formas posibles de hacer eso.

  1. Opción

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

  1. Opción

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

  1. Opción

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


Probablemente usaría un Left Join, que devolverá las filas incluso si no hay coincidencia, y luego puede seleccionar solo las filas sin coincidencia marcando NULLs.

Entonces, algo como:

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

Si eso es más o menos eficiente que usar una subconsulta, depende de la optimización, los índices, si es posible tener más de una eliminación por votante, etc.


Usaría un ''donde no existe'', exactamente como sugieres en tu título:

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

Eso puede ser marginalmente más rápido que hacer un join a la izquierda (por supuesto, dependiendo de tus índices, cardinalidad de tus tablas, etc.), y es casi seguro mucho más rápido que usar IN.