존재하지 않는 MySQL 가입


80

두 테이블을 조인하는 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 

답변:


191

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가 왼쪽에서 모든 행에 대해 오른쪽 테이블에 모든 레코드를 저장하지 않으려는 경우.
Arthur Kushman

1
어떻게 당신이 존재하지 않는 행을 찾기 위해이 쿼리를 수정 할 EE.voter_id할 수있다 NULL우리가하고있는 데이터 세트에서 JOIN에서 보내고?
Danny Beckett

일부 공통 열 또는 관련 값과 함께 테이블을 연결해야합니다. :하지만이 (테스트되지 않은) 일 수 있다고 생각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

왼쪽 조인을 수행하는 것보다 약간 더 빠를 수 있으며 (물론 인덱스, 테이블의 카디널리티 등에 따라 다름) IN을 사용하는 것보다 훨씬 빠릅니다.


감사합니다-확실히 더 빨랐습니다.
spidie 2013 년

6

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

  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
    )
    
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.