MySQL Join, где не существует - PullRequest
66 голосов
/ 15 апреля 2009

У меня есть запрос MySQL, который объединяет две таблицы

  • Голосовавшие
  • Домохозяйства они присоединяются к избирателей.household_id и House.id

    Теперь, что мне нужно сделать, это изменить его там, где таблица избирателей соединена с третьей таблицей, называемой исключением, вдоль voter.id и el elivivo.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 

Ответы [ 3 ]

155 голосов
/ 15 апреля 2009

Я бы, вероятно, использовал левое соединение, которое будет возвращать строки, даже если совпадений нет, и тогда вы можете выбрать только строки без совпадений, проверив NULL.

Итак, что-то вроде:

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

Является ли это более или менее эффективным, чем использование подзапроса, зависит от оптимизации, индексов, возможно ли иметь более одного исключения на одного избирателя и т. Д.

4 голосов
/ 08 мая 2009

Я бы использовал «где не существует» - именно так, как вы предлагаете в заголовке:

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

Это может быть незначительно быстрее, чем выполнение левого соединения (конечно, в зависимости от ваших индексов, количества таблиц и т. Д.), И почти наверняка намного быстрее, чем использование IN.

3 голосов
/ 07 апреля 2017

Есть три возможных способа сделать это.

  1. Опция
        SELECT  lt.* FROM    table_left lt
        LEFT JOIN
            table_right rt
        ON      rt.value = lt.value
        WHERE   rt.value IS NULL
  1. Опция
        SELECT  lt.* FROM    table_left lt
        WHERE   lt.value NOT IN
        (
        SELECT  value
        FROM    table_right rt
        )
  1. Опция
        SELECT  lt.* FROM    table_left lt
        WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    table_right rt
        WHERE   rt.value = lt.value
        )
...