이중 부정 SQL을 읽습니다.

3397 단어 SQL
Qiita 게시물 #29

이번에는...
「달인에게 배우는 SQL 철저 지남서 제2판」에서 해설되고 있는 이중 부정 쿼리가 확실히 이해할 수 없었기 때문에, 그 때의 비망록입니다.

테이블 및 검색 내용 정의



테이블은 다음과 같습니다.

테이블 이름: Teams


member
team_id
status



1
  대기


1
 출동중


1
  대기

카렌
2
 출동중

키스
2
 휴가


3
  대기

심장
3
  대기


3
  대기

베스
4
  대기

알렌
5
 출동중

로버트
5
 휴가

케이건
5
 대기  


취득 내용 : 이 중에서 팀의 전원이 대기중인 멤버를 취득합니다.
SELECT team_id, member
  FROM Teams T1
  WHERE NOT EXISTS (SELECT *
                      FROM Teams T2
                      WHERE T1.team_id = T2.team_id
                      AND status <> '待機');

쿼리 실행 결과:


team_id
member


3


3
심장

3


4
베스


해설



이 쿼리를 언어화하면 ...
"팀에서 대기 중이 아닌 멤버가 존재하지 않는다"입니다.
일본어로도 까다 롭습니다
조금 더 쿼리 문장에 언어화하면 ...
"팀이 동일하고, 상태가 대기라는 조건의 반환값이 없는 팀을 취득한다"입니까.
WHERE구 안이 다소 어렵기 때문에, 이쪽에 포커스 해 해독해 갑니다.
WHERE NOT EXISTS 
(SELECT *
   FROM Teams T2
   WHERE T1.team_id = T2.team_id
   AND status <> '待機');
  • 1명이라도 대기 이외라면 데이터를 취득할 수 있으므로 NOT EXISTS로 연주됩니다. 따라서 전원이 대기하면 1행도 취득할 수 없고 NOT EXISTS로 조건과 일치합니다.
  • WHERE T1.team_id = T2.team_id 는 테이블을 자체 조인하고 팀을 그룹화하기 때문에 GROUP BY team_id 와 같은 의미입니다.
  • status <> '待機' 에서 「대기가 아니다」라고 하는 비교를 하고 있습니다.
  • 팀 1과 팀 2, 팀 5는 3.의 "대기하지 않음"에 해당하는 멤버가 있기 때문에 행이 취득됩니다.
  • 팀 3과 팀 4는 "대기하지 않음"에 모두 적용되지 않으므로 행을 얻을 수 없습니다.
  • 따라서 얻을 수 없었던 팀이 NOT EXISTS로 true가 되어 상기의 팀이 좁혀져 취득됩니다.

  • 복잡한 쿼리에서도 FROM->WHERE->GROUP BY->HAVING->ORDER BY->SELECT 의 순서로 하나씩 처리해 나가면 혼란 없이 실행할 수 있을 것 같습니다.
    하위 쿼리도 혼동시키지 않고 하나의 쿼리로 분해하면 점차 스트레스없이 읽을 수있을 것 같습니다.

    좋은 웹페이지 즐겨찾기