[mysql] 존재하지 않는 MySQL 가입

두 테이블을 조인하는 MySQL 쿼리가 있습니다.

  • 유권자
  • 가구

그들은에 가입 voters.household_id하고 household.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



답변

LEFT JOIN일치하는 항목이 없어도 행을 반환하는을 사용하고 NULLs 를 확인하여 일치하지 않는 행만 선택할 수 있습니다 .

따라서 다음과 같습니다.

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

하위 쿼리를 사용하는 것보다 효율성이 떨어지는 지 여부는 최적화, 인덱스, 투표자 당 둘 이상의 제거가 가능한지 여부 등에 따라 다릅니다.


답변

제목에서 제안한대로 정확히 ‘존재하지 않는 곳’을 사용합니다.

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을 사용하는 것보다 훨씬 빠릅니다.


답변

이를 수행하는 세 가지 가능한 방법이 있습니다.

  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
    )
    


답변