I have a MySQL query that joins two tables
They join on voters.household_id
and household.id
There are three possible ways to do that.
Option
SELECT lt.* FROM table_left lt
LEFT JOIN
table_right rt
ON rt.value = lt.value
WHERE rt.value IS NULL
Option
SELECT lt.* FROM table_left lt
WHERE lt.value NOT IN
(
SELECT value
FROM table_right rt
)
Option
SELECT lt.* FROM table_left lt
WHERE NOT EXISTS
(
SELECT NULL
FROM table_right rt
WHERE rt.value = lt.value
)
I'd use a 'where not exists' -- exactly as you suggest in your title:
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
That may be marginally faster than doing a left join (of course, depending on your indexes, cardinality of your tables, etc), and is almost certainly much faster than using IN.
I'd probably use a LEFT JOIN
, which will return rows even if there's no match, and then you can select only the rows with no match by checking for NULL
s.
So, something like:
SELECT V.*
FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id
WHERE E.voter_id IS NULL
Whether that's more or less efficient than using a subquery depends on optimization, indexes, whether its possible to have more than one elimination per voter, etc.