[SQL] SQL Subquery

박미영·2023년 4월 26일
0

DataSchool StudyNote - SQL

목록 보기
12/12

📌Subquery

하나의 SQL 문 안에 포함되어 있는 또 다른 SQL 문을 말한다.
메인쿼리가 서브쿼리를 포함하는 종속적인 관계이다.

  • 서브쿼리는 메인쿼리의 칼럼 사용 가능
  • 메인쿼리는 서브쿼리의 칼럼 사용 불가

⚠️Subquery 사용시 주의할 점

  • Subquery 는 괄호로 묶어서 사용
  • 단일 행 혹은 복수 행 비교 연산자와 함께 사용 가능
  • subquery 에서는 order by 를 사용X



📌Subquery 종류

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



- 스카라 서브쿼리 (Scalar Subquery)

SELECT 절에서 사용하는 서브쿼리. 결과는 하나의 Column 이어야 한다.

SELECT column1, (SELECT column2 FROM table2 WHERE condition)
FROM table
WHERE condition;



- 예제
서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균 강도 검거 건수를 조회

select case_number,
	(select avg(case_number)
	from crime_status
	where crime_type LIKE '강도' AND status_type LIKE '검거') avg
from crime_status
where police_station like '은평' and crime_type like '강도' and status_type like '검거';





- 인라인 뷰 (Inline View)

FROM 절에 사용하는 서브쿼리. 메인쿼리에서는 인라인 뷰에서 조회한 Column 만 사용가능

SELECT a.column, b.column
FROM table1 a, (SELECT column1, column2 FROM table2) b
WHERE condition;



- 예제
경찰서 별로 가장 많이 발생한 범죄 건수와 범죄 유형을 조회

  1. 경찰서 별로 가장 많이 발생한 범죄 건수
SELECT police_station, max(case_number) count
FROM crime_status
WHERE status_type LIKE '발생'
GROUP BY police_station;


  1. 경찰서 별로 가장 많이 발생한 범죄 건수와 범죄 유형을 조회
    (1번 결과 값의 범죄 유형을 찾으면 됨)
select c.police_station, c.crime_type, c.case_number
FROM crime_status c,
	(SELECT police_station, max(case_number) count
	FROM crime_status
    WHERE status_type LIKE '발생'
    GROUP BY police_station) m
WHERE c.police_station = m.police_station AND c.case_number = m.count;





- 중첩 서브쿼리(Nested Subquery)

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

  • Single Row - 하나의 열을 검색하는 서브쿼리
  • Multiple Row - 하나 이상의 열을 검색하는 서브쿼리
  • Multiple Column - 하나 이상의 행을 검색하는 서브쿼리



- Single Row

하나의 열을 검색하는 서브쿼리

서브쿼리가 비교연산자( =, >, >=, <, <=, <>, !=)와 사용되는 경우,
서브쿼리의 검색 결과는 한 개의 결과값을 가져야 한다. (두개 이상인 경우 에러)

SELECT column_names
FROM table_name
WHERE column_name = (SELECT column_names
					FROM table_name
                    WHERE condition)
ORDER BY column_name;



Single Row Subquery 예제 - 괄호 없이 (에러)

select name from celeb where name = select host from snl_show;



Single Row Subquery 예제 - 한 개 이상의 결과 (에러)

select name from celeb where name = (select host from snl_show);



Single Row Subquery 예제

select name from celeb where name = (select host from snl_show where id = 1);





- Multiple Row

하나 이상의 열을 검색하는 서브쿼리

- Multiple Row(IN)

서브쿼리 결과 중에 포함 될때

SELECT column_names
FROM table_name
WHERE column_name IN (SELECT column_names
					FROM table_name
                    WHERE condition)
ORDER BY column_names;



Multiple Row - IN 예제
SNL 에 출연한 영화배우를 조회

select host
from snl_show
where host in (select name
			   from celeb
 			   where job_title like '%연기자%');




- Multiple Row(EXISTS)

서브쿼리 결과에 값이 있으면 반환

SELECT column_names
FROM table_name
WHERE EXISTS (SELECT column_names
			  FROM table_name
              WHERE condition)
ORDER BY column_names;



Multiple Row - EXISTS 예제
범죄 검거 혹은 발생 건수가 2000건 보다 큰 경찰서 조회

select name
from police_station p
where exists (select police_station
			  from crime_status c
			  where p.name = c.reference AND case_number >2000);




- Multiple Row(ANY)

서브쿼리 결과 중에 최소한 하나라도 만족하면 (비교연산자 사용)

SELECT column_names
FROM table_name
WHERE column_name = ANY (SELECT column_names
						 FROM table_name
                    	 WHERE condition)
ORDER BY column_names;



Multiple Row - ANY 예제
SNL 에 출연한 적이 있는 연예인 이름 조회

select name
from celeb
where name = any (select host
				  from snl_show);




- Multiple Row(ALL)

서브쿼리 결과를 모두 만족하면 (비교 연산자 사용)

SELECT column_names
FROM table_name
WHERE column_name = ALL (SELECT column_names
						 FROM table_name
                    	 WHERE condition)
ORDER BY column_names;



Multiple Row - ALL 예제
서브쿼리 결과를 모두 만족하면 (비교 연산자 사용)

select name
from celeb
where name = all (select host
				  from snl_show
				  where id=1);





- Multi Column Subquery(연관 서브쿼리)

하나 이상의 행을 검색하는 서브쿼리
서브쿼리 내에 메인쿼리 컬럼이 같이 사용되는 경우

SELECT column_names
FROM table_name a
WHERE (a.column1, a.column2, ...) IN (SELECT (b.column1, b.column2, ...)
						 			  FROM table_name b
                    	 			  WHERE a.column_name = b.column_name)
ORDER BY column_names;



Multi Column Subquery 예제
강동원과 성별, 소속사가 같은 연예인의 이름, 성별, 소속사를 조회

select name, sex, agency
from celeb
where (sex, agency) in (select sex, agency from celeb where name='강동원');



Subquery 문제

  1. oil_price 테이블에서 셀프주유의 평균가격과 SK에너지의 가장 비싼 가격을 Scalar Subquery 를 사용하여 조회
select max(가격), (select avg(가격) from oil_price where 셀프='Y')
    -> from oil_price
    -> where 상표='SK에너지';



  1. oil_price 테이블에서 상표별로 가장 비싼 가격과 상호를 Inline View 를 사용하여 조회하세요.
select o.상호, o.상표, s.max_price
from oil_price o,
(select 상표, max(가격) max_price from oil_price group by 상표) s
where o.상표 = s.상표 and o.가격 = s.max_price;



  1. 평균가격 보다 높은 주유소 상호와 가격을 Nested Subquery 를 사용하여 조회하세요.
  • 평균 가격

select 상호, 가격
from oil_price
where (select avg(가격) from oil_price) < 가격;



  1. 3번에서 조회한 주유소에서 주유한 연예인의 이름과 주유소, 주유일을 Nested Subquery 를 사용하여 조회하세요. (refueling 테이블)



  1. refueling 테이블과 oil_price 테이블에서 10만원 이상 주유한 연예인 이름, 상호, 상표, 주유 금액, 가격을 Inline View 를 사용하여 조회하세요.




😊

서브쿼리는 처음 사용해보는거라 이해하려면 한 번 더 코드를 꼼꼼히 보고 좀 더 예제를 풀어봐야할 듯 하다.
내일 할 SQL 과제 풀고 나면 실력이 나아져 있을 거라 믿으며🤣


"이 글은 제로베이스 데이터 취업 스쿨 강의를 듣고 작성한 내용으로 제로베이스 데이터 취업 스쿨 강의 자료 일부를 발췌한 내용이 포함되어 있습니다."

0개의 댓글