programing

존재하지 않는 MySQL 가입

bestcode 2022. 9. 18. 12:54
반응형

존재하지 않는 MySQL 가입

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

  • 유권자
  • 가구

그들은 에 합류한다.voters.household_id그리고.household.id.

이제 제가 해야 할 일은 유권자 테이블이 엘리미네이션이라는 세 번째 테이블과 결합되어 있는 부분을 수정하는 것입니다.voter.id그리고.elimination.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

서브쿼리를 사용하는 것보다 효율이 높은지 낮은지는 최적화, 인덱스, 유권자 1명당 2회 이상 제거 가능 여부 등에 따라 달라집니다.

'존재하지 않는 곳'을 사용하겠습니다. 제목에서 제안하신 그대로입니다.

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
    )
    

LEFT JOINs - LEFT JOINs는 기본적으로 OUTER JOINs입니다.RDBMS 쿼리 파서와 옵티마이저에 따라 OUTER JOINs 처리가 매우 다를 수 있습니다.예를 들어 LEFT(OUTER) JOINS가 MySQL의 쿼리 옵티마이저에 의해 해석되는 방법 및 반복마다 평가할 수 있는 실행 계획의 차이를 예로 들 수 있습니다.

https://dev.mysql.com/doc/refman/8.0/en/outer-join-simplification.html

LEFT JOIN은 본질적으로 항상 비결정론적입니다.IMO - 프로덕션 코드에서는 사용하지 마십시오.

저는 먼저 JOIN 유형의 스테이트먼트를 좀 더 "구식" 접근법으로 쓰는 것을 선호하며, 구체적인 JOIN 선언은 생략합니다.RDBMS 쿼리 파서가 설계한 작업을 수행하도록 합니다. 즉, 스테이트먼트를 분석하고 인덱스 통계 및 데이터 모델 설계에 대한 평가를 바탕으로 최적의 실행 계획으로 변환합니다.단, 쿼리 파서/옵티마이저 빌드는 잘못될 수도 있습니다.여러 번 봐왔습니다.일반적으로 먼저 이 방법을 사용하면 대부분의 경우 정보에 입각한 추가 조정 결정을 내리기에 충분한 기준 정보를 얻을 수 있다고 생각합니다.

설명하려면 - 이 스레드의 질문 쿼리를 사용합니다.

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

위의 명시적인 JOIN 및 NOT EXISTES 문구를 사용하지 않고 다시 작성되었다고 간주합니다(WHERE 절의 완전하지 않은 필드가 유권자 테이블에 속한다고 가정합니다).

SELECT v.`ID`, v.`Last_Name`, v.`First_Name`,
       v.`Middle_Name`, v.`Age`, v.`Sex`,
       v.`Party`, v.`Demo`, v.`PV`,
       h.`Address`, h.`City`, h.`Zip`
FROM `voter` v, `household` h, `elimination` e
WHERE v.`House_ID` = h.`id`
AND v.`ID` != e.`voter_id`
AND v.`CT` = '5'
AND v.`Precnum` = 'CTY3'
AND  v.`Last_Name`  LIKE '%Cumbee%'
AND  v.`First_Name`  LIKE '%John%'
ORDER BY v.`Last_Name` ASC
LIMIT 30;

미래의 SQL 쿼리 중 몇 가지를 구문적으로 작성하고 결과를 비교한 후 어떻게 생각하는지 확인해 보십시오.위에서 제시한 스타일로 SQL을 작성하면 RDBMS에 의존하지 않는다는 이점도 있습니다.

건배!

언급URL : https://stackoverflow.com/questions/750343/mysql-join-where-not-exists

반응형