MySQL联接不存在的地方


79

我有一个连接两个表的MySQL查询

  • 选民
  • 住户

他们加入voters.household_idhousehold.id

现在,我需要做的是修改它,在投票器表与第三个表称为“消除”的地方,沿着voter.idelimination.voter_id。但是要注意的是,我要排除选民表中在淘汰表中具有相应记录的所有记录。

如何制作查询来做到这一点?

这是我当前的查询:

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 

Answers:


190

我可能会使用LEFT JOIN,即使没有匹配项也会返回行,然后可以通过检查NULLs仅选择不匹配的行。

因此,类似:

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

与使用子查询相比,效率更高还是更低,取决于优化,索引,每个选民是否有多个消除对象等。


3
高负载时,子查询的速度要快+1。如果U可以执行JOIN而不是子查询,则可以+进行子查询-只需执行JOIN,对于分析器来说,它们要简单得多。另一个有用的例子是,如果右表中有一些行或没有,则U可能希望得到结果:SELECT V.* FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id OR E.voter_id IS NULL例如:如果U不想为左表中的每一行将所有记录存储在右表中。
亚瑟·库什曼

1
您将如何修改此查询以查找中不存在的行E(何时E.voter_id可以出现NULL在我们所要使用的数据集中)JOIN
丹尼·贝克特

您需要将表与一些公共列或相关值链接在一起。但我认为这可能会起作用(未经测试):SELECT V.*, COUNT(E.*) AS `countE` FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id WHERE countE = 0;
ericek111

7

我会使用“不存在的地方”-正是您在标题中所建议的:

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

这可能是稍快比做左连接(当然,这取决于您的索引,你的表的基数,等等),并且几乎可以肯定得多比使用更快。


谢谢你-绝对对我来说更快。
spidie

5

有三种可能的方法可以做到这一点。

  1. 选项

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

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

    SELECT  lt.* FROM    table_left lt
    WHERE   NOT EXISTS
    (
    SELECT  NULL
    FROM    table_right rt
    WHERE   rt.value = lt.value
    )
    
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.