CH 17. SQL Subquery

이진호·2024년 10월 9일

SQL Subquery (서브쿼리) 란?

하나의 SQL문 안에 포함된 또 다른 SQL문을 말합니다.

주의사항

(1) 서브쿼리는 메인쿼리의 컬럼 사용 O, 메인쿼리는 서브쿼리의 컬럼 사용 X
(2) 서브쿼리는 괄호로 묶어서 사용
(3) 단일 행 or 복수 행 비교 연산자와 사용 가능
(4) 서브쿼리에서는 order by 사용 X

서브쿼리 종류

  • 스칼라 서브쿼리 (Scalar Subquery) : SELECT 절에 사용
  • 인라인 뷰 (Inline View) : FROM 절에 사용
  • 중첩 서브쿼리 (Nested Subquery) : WHERE 절에 사용

스칼라 서브쿼리 예시

//select 절에서 사용하는 서브쿼리.
//서브쿼리의 결과는 하나의 column이어야 함!!
select 컬럼명1, (select 컬럼명2 from 테이블명2 where 조건)
from 테이블명1
where 조건;

실습 문제
은평 경찰서에서 검거괸 강도 건수와 서울시 전체 경찰서에서 검거된 평균 강도 건수를 조회하세요.

실습 문제
oil_price 테이블에서 셀프 주유의 평균 가격과 SK에너지의 가장 비싼 가격을 조회하세요.

인라인 뷰 예시

//FROM 절에서 사용하는 서브쿼리
//메인쿼리에서는 인라인 뷰에서 조회한 컬럼만 사용 가능함!!
select a.column, b.column
from table1 a, (select column1, column2 from table2) b
where 조건;

실습 문제
서울시 경찰서별로 가장 많이 발생한 범죄의 유형과 건수를 조회하세요.
(1) 서울시 경찰서별로 발생한 범죄의 최대 건수 알기

select police_station, max(case_number) count
from crime_status
where status_type like '발생'
group by police_station;

(2) (1)의 결과와 crime_status를 인라인뷰로 join하여 문제 풀기

실습 문제
oil_price 테이블에서 상표별로 가장 비싼 가격과 상호를 조회하세요.
(1) 상표별 max 가격 조회하기

(2) (1)에서 조회한 결과와 oil_price로 문제 풀기

중첩 서브 쿼리

WHERE 절에서 사용하는 서브쿼리

  • Single Row : 하나의 열을 검색하는 서브쿼리
  • Multiple Row : 여러 열을 검색하는 서브쿼리
  • Multiple Column : 여러 행을 검색하는 서브쿼리

중첩 서브 쿼리 : Single Row

서브쿼리가 비교연산자(=, >, >=, ...)와 사용되는 경우,
서브쿼리의 검색 결과는 한 개의 결과값을 가져야 합니다.

select column_names
from table_name
where column_name = (select column_name from table_name where 조건)
order by column_name;

Single Row 에러 상황 1

괄호 없이 사용할 경우, 에러가 납니다.

Single Row 에러 상황 2

여러 개의 결과를 리턴할 경우, 에러가 납니다.

Single Row 알맞게 쓴 상황

중첩 서브 쿼리 : Multiple Row

(1) IN

서브쿼리 결과 중에 포함(IN)되는지를 조건으로 둘 때 사용합니다.

select column_names
from table_name
where column_name IN (select column_name from table_name where condition)
order by column_names;
SELECT * FROM test WHERE score IN(700, 800, 900);
//score=700 or score=800 or score=900 과 같은 의미

(2) EXISTS

  • 서브쿼리 결과 중에 존재(EXISTS)하는지를 조건으로 둘 때 사용합니다.
  • 즉, 만족하는 값이 하나라도 있으면 TRUE가 됩니다.
  • NOT EXISTS 연산자는 일치하는 값이 하나도 없으면 메인 쿼리 결과의 모든 행을 반환합니다.
select column_names
from table_name
where EXISTS (select column_name from table_name where condition)
order by column_names;

(3) ANY

  • 서브쿼리 결과 중에 하나라도 만족하는지를 조건으로 둘 때 비교연산자와 함께 사용합니다.
  • 나올 수 있는 결과에 모두 OR 연산자를 사용한 것과 같은 결과를 얻습니다.
select column_names
from table_name
where column_name = ANY (select column_name from table_name where condition)
order by column_names;
SELECT * FROM test WHERE score = ANY(700, 800, 900);
//score=700 or score=800 or score=900 과 같은 의미

SELECT * FROM test WHERE score > ANY(700, 800, 900);
//score>700 or score>800 or score>900 과 같은 의미
//비교연산자 <, >=, <= 등도 동일한 원리

(4) ALL

  • 서브쿼리 결과를 모두 만족하는지를 조건으로 둘 때 비교연산자와 함께 사용합니다.
  • 나올 수 있는 결과에 모두 AND 연산자를 사용한 것과 같은 결과를 얻습니다.
select column_names
from table_name
where column_name = ALL (select column_name from table_name where 조건)
order by column_names;
SELECT * FROM test WHERE score = ALL(700, 800, 900);
//이 쿼리의 반환값은 없음. (FALSE)
//왜냐하면 700, 800, 900을 모두 만족할 수는 없기 때문

SELECT * FROM test WHERE score > ALL(700, 800, 900);
//score>700 and score>800 and score>900 과 같은 의미

중첩 서브 쿼리 : Multiple Column

실습 문제
1번. 평균가격보다 높은 주유소의 상호와 가격을 조회하세요.

2번. 1번에서 조회한 주유소에서 주유한 연예인의 이름과 주유소, 주유일을 조회하세요.
oil_price.상호 = refueling.주유소

3번 refueling 테이블과 oil_price 테이블에서 10만원 이상 주유한 연예인의 이름, 상호, 상표, 주유 금액, 가격을 조회하세요.
(1) 10만원 이상 주유한 연예인의 이름, 주유소, 금액 얻기

(2) (1)에서 나온 주유소들의 정보를 알고 싶은 것이므로, oil_price와 join하여 문제 풀기

🔵 흥미로웠던 점 :
subquery에 집중하느라 join을 하지 않는 경우가 있었는데, join을 하고/하지 않고에 따라 엄청 큰 차이가 있었다. 검색해보니 join을 하지 않으면 결과값끼리 카티전 곱을 수행하여 중복된 값이 방대해진다는데, 주의해야겠다 ㄷㄷ

🔵 다음 학습 계획 :
Git에 대해 학습할 예정입니다.

0개의 댓글