[데이터베이스] 13. SQL 서브 쿼리

2024. 10. 21. 07:03·CS/기초데이터베이스
반응형

SQL의 쿼리는 FROM, WHERE, HAVING 절 안에서도 중첩되어 등장할 수 있다.

103번 보트를 예약한 선원의 이름을 출력할 때 다음과 같이 중첩된 쿼리를 통해서도 문제를 해결할 수 있다.

 

 

이는 마치 중첩된 반복문을 작성하는 것과 비슷하다.

선원 테이블에서 모든 선원을 가져오고, 각 선원에 대해서 돌면서 (for each) 예약테이블을 돌면서 선원 정보를 찾는 것과 비슷하다.

이때 IN 연산자는 집합 연산자로서 해당 서브쿼리의 결과 집합에 S.sid 가 존재하는 sid 만을 조회한다.

 

 

서브쿼리와 관련된 간단한 연습문제를 몇 가지 풀어보자.

 

1. 빨간색 배를 예약한 적이 있는 / 없는 선원 이름 조회

SELECT S.sname
FROM sailors S
WHERE S.sid IN (
    SELECT R.sid
    FROM Reserves R, Boats B
    WHERE R.bid = B.bid AND B.color = 'red'
)

 

예약한 적이 없는 선원은 IN 을 NOT IN 으로 바꾸면 된다.

 

 

103번 보트를 예약한 선원의 이름을 조회할 때, 다음과 같이 쿼리를 작성할 수도 있다.

 

그림에서 보는 것처럼, 서브쿼리에는 바깥에 있는 쿼리의 테이블 데이터를 참조할 수 있다.

EXISTS 연산자는 해당 집합이 공집합인지 아닌지를 검사하며, 공집합이 아니라면 TRUE 를 반환한다.

이 SQL의 실행 과정은 역시 중첩 반복문처럼 생각하면 된다.

각 Sailors 의 튜플에 대해 서브 쿼리가 반복적으로 실행되면서 그 조건이 TRUE 가나오는 튜플만을 선별한다.

 

(강의록에서는 EXISTS 자리에 UNIQUE 도 사용할 수 있는 것처럼 말하는데, postgresql 기준으로는 지원하지 않는 것 같다.)

 


 

EXISTS 외에도 op ANY, op ALL 과 같은 연산자도 있다.

이 연산자는 op 를 만족하는 튜플이 하나라도 있으면 참 (any), 모든 튜플에 대해 op를 만족하면 참 (all) 을 명시할 수 있다.

 

예를 들면 다음과 같은 문제를 푸는데 사용될 수 있다.

 

 

2. 'Horatio' 라는 이름의 선원들 중 적어도 한 명보다 등급이 높은 선원 찾기

SELECT *
FROM sailors S
WHERE S.rating > ANY (SELECT S2.rating
                      FROM sailors S2
                      WHERE S2.sname = 'Horatio');

 

 

3. 'Horatio' 라는 이름의 선원들 모두보다 등급이 높은 선원 찾기

'Horatio' 라는 이름의 선원들 중 제일 높은 등급을 가진 사람보다 더 큰 등급을 갖는 사람을 찾는 것과도 같다.

SELECT *
FROM sailors S
WHERE S.rating > ALL (SELECT S2.rating
                      FROM sailors S2
                      WHERE S2.sname = 'Horatio');

 

 

4. 가장 높은 등급을 가진 선원 찾기

SELECT *
FROM sailors S
WHERE S.rating >= ALL (SELECT S2.rating
                       FROM sailors S2);

 

 

 

또는 max() 집계함수를 사용하여

SELECT *
FROM sailors S
WHERE S.rating = (SELECT max(S2.rating)
                  FROM sailors S2);

 

이렇게 해도 된다.

 

 

5. 빨간 배, 녹색 배를 둘 다 예약한 적이  있는 선원의 이름

이전 글에서 기본 쿼리를 정리할 때 INTERSECT 를 사용해서 풀었던 문제다.

만약 SQL 에서 INTERSECT를 지원하지 않는다면 다음과 같이 서브쿼리와 IN 을 사용해서 풀 수 있다.

SELECT S.sname
FROM sailors S, Reserves R, Boats B
WHERE S.sid = R.sid AND R.bid = B.bid
AND B.color = 'red'
AND S.sid IN (SELECT S2.sid
              FROM sailors S2, Reserves R2, Boats B2
              WHERE S2.sid = R2.sid AND R2.bid = B2.bid
              AND B2.color = 'green');

 

 

 


마지막으로 관계 대수에서 division 연산을 기본 연산으로 바꾸어서 표현했던 것처럼,

division 연산을 SQL로 작성해보자.

 

6. 모든 배를 예약한 적이 있는 선원의 이름 구하기

모든 배를 예약한 적이 있다는 것은, 이 사람이 예약한 배 리스트를 전체 배 리스트와 차집합 연산한 결과가 공집합이라는 것과 같다.

(전체 배 리스트 - 이 사람이 예약한 배 리스트 = φ)

 

SELECT S.sname
FROM sailors S
WHERE NOT EXISTS (SELECT B1.bid
                  FROM Boats B1
                  EXCEPT
                  SELECT R.bid
                  FROM Reserves R
                  WHERE R.sid = S.sid);

 

 

만약 EXCEPT 를 지원하지 않으면 NOT IN 연산자를 사용하면 된다.

이 풀이는 생략한다. (Postgresql 은 잘 지원하는듯)

 

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'CS > 기초데이터베이스' 카테고리의 다른 글

[데이터베이스] 15. Null, 제약조건, Trigger  (0) 2024.10.21
[데이터베이스] 14. SQL 집계 함수와 Group By  (0) 2024.10.21
[데이터베이스] 12. SQL 기본 쿼리  (0) 2024.10.20
[데이터베이스] 11. 관계 대수 연습 문제  (0) 2024.10.19
[데이터베이스] 10. 관계 대수  (0) 2024.10.19
'CS/기초데이터베이스' 카테고리의 다른 글
  • [데이터베이스] 15. Null, 제약조건, Trigger
  • [데이터베이스] 14. SQL 집계 함수와 Group By
  • [데이터베이스] 12. SQL 기본 쿼리
  • [데이터베이스] 11. 관계 대수 연습 문제
에버듀
에버듀
개발은 좋은데 뭘로 개발할까
  • 에버듀
    Blog. 에버듀
    에버듀
  • 전체
    오늘
    어제
    • 분류 전체보기 (614)
      • 개인 프로젝트 (43)
        • 토이 프로젝트 (3)
        • [2020] 카카오톡 봇 (9)
        • [2021] 코드악보 공유APP (22)
        • [2022] 유튜브 뮤직 클론코딩 (9)
        • [2025] 한글 SQL 데이터베이스 (0)
      • 팀 프로젝트 (22)
        • [2020] 인공지능 숫자야구 (4)
        • [2022] OSAM 온라인 해커톤 (10)
        • [2024] GDSC 프로젝트 트랙 (6)
        • [2025] 큰소리 웹 페이지 (2)
      • CS (335)
        • 자료구조 (19)
        • 어셈블리 (41)
        • 멀티미디어응용수학 (7)
        • 컴퓨터 구조 (29)
        • 알고리즘 분석 (4)
        • 컴퓨터 네트워크 (38)
        • 프로그래밍언어론 (15)
        • HCI 윈도우즈프로그래밍 (26)
        • 기초데이터베이스 (29)
        • 운영체제 (23)
        • 오토마타 (24)
        • 문제해결기법 (11)
        • 블록체인 (22)
        • 소프트웨어공학 (21)
        • 기계학습심화 (12)
        • 컴퓨터그래픽스와 메타버스 (8)
        • 분산시스템특론 (6)
      • 자기계발 (44)
        • 생각 정리 (22)
        • 대외활동 (11)
        • 동아리 (7)
        • 자격증 (3)
        • 머니 스터디 (1)
      • 알고리즘 (PS) (107)
        • BOJ (101)
        • Programmers (5)
        • 알고리즘 이모저모 (1)
      • WEB(BE) (8)
        • express.js (1)
        • Spring & Spring Boot (7)
      • WEB(FE) (2)
        • html, css, js (1)
        • React.js (1)
      • Tool & Language (6)
        • Edit Plus (1)
        • Git (1)
        • Python3 (2)
        • Java (2)
      • Infra (12)
        • AWS (1)
        • Oracle Cloud (8)
        • Firebase (2)
        • Network (1)
      • Android (18)
        • Java (6)
        • Flutter (12)
      • Window (2)
        • Visual Studio 없이 WPF (1)
        • MFC (1)
      • 독서 (14)
        • Inside Javascript (7)
        • Database Internals (6)
        • 한 글 후기 (1)
  • 링크

    • github
    • website
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
에버듀
[데이터베이스] 13. SQL 서브 쿼리
상단으로

티스토리툴바