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.
- Opción
SELECT lt.* FROM table_left lt LEFT JOIN table_right rt ON rt.value = lt.value WHERE rt.value IS NULL
- Opción
SELECT lt.* FROM table_left lt WHERE lt.value NOT IN ( SELECT value FROM table_right rt )
- 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.