-
1. Subquery란? 쿼리 안의 쿼리라는 의미입니다. 하위 쿼리의 결과를 상위 쿼리에서 사용하면, SQL 쿼리가 훨씬 간단해져요!
즉, Subquery를 사용하지 않아도 원하는 데이터를 얻어낼 수 있겠지만, 더 편하고 간단하게 원하 는 데이터를 얻기 위해 사용되는 파워풀한 기능입니다. Subquery에 대한 이해도가 생기면, With구문을 이용해서 더 간단하게 만들어볼게요!
(1)kakaopay로 결제한 유저들의 정보 보기 → 우선, 이렇게 볼 수 있겠죠? users 와 orders 의 inner join으로!
select u.user_id, u.name, u.email from users u inner join orders o on u.user_id = o.user_id where o.payment_method = 'kakaopay'
(2)우선 kakaopay로 결제한 user_id를 모두 구해보기 → K 라고 합시다
select user_id from orders where payment_method = 'kakaopay'
(3)그 후에, user_id가 K 에 있는 유저들만 골라보기
→ 이게 바로 서브쿼리!
select u.user_id, u.name, u.email from users u where u.user_id in ( select user_id from orders where payment_method = 'kakaopay'
2. 자주 쓰이는 Subquery 유형 알아보기
자주 쓰는 Subquery를 먼저 알아볼까요? Subquery는 where, select, from 절에서 유용하게 사용될 수 있어
1) Where 에 들어가는 Subquery
Where은 조건문이죠? Subquery의 결과를 조건에 활용하는 방식으로 유용하게 사용합니 다. where 필드명 in (subquery) 이런 방식으로요!
(1)예를 들면, 카카오페이로 결제한 주문건 유저들만, 유저 테이블에서 출력해주고 싶을 때는 아래와 같이 표현할 수 있겠죠.
select * from users u where u.user_id in (select o.user_id from orders o
(2)쿼리가 실행되는 순서를 이렇게 상상하면 편해요!
{1} from 실행: users 데이터를 가져와줌
{2} Subquery 실행: 해당되는 user_id의 명단을 뽑아줌
{3} where .. in 절에서 subquery의 결과에 해당되는 'user_id의 명단' 조건으로 필터링 해줌
{4} 조건에 맞는 결과 출력
2) Select 에 들어가는 Subquery
Select는 결과를 출력해주는 부분이죠? 기존 테이블에 함께 보고싶은 통계 데이터를 손쉽게 붙이는 것에 사용합니다. select 필드명, 필드명, (subquery) from .. 이렇게요!
앞서 보았던것처럼, '오늘의 다짐' 데이터를 보고 싶은데 '오늘의 다짐' 좋아요의 수가, 본인이 평소 에 받았던 좋아요 수에 비해 얼마나 높고 낮은지가 궁금할 수 있겠죠? 그럼, 평균을 먼저 구해봅시다! user_id='4b8a10e6' 를 예시로!
select avg(likes) from checkins c2 where c2.user_id = '4b8a10e6'
그러면, 이렇게 표현할 수 있어요!
select c.checkin_id, c.user_id, c.likes, (select avg(likes) from checkins c2 where c2.user_id = c.user_id) as avg_like_user from checkins c;
쿼리가 실행되는 순서를 이렇게 상상하면 편해요!
{1} 밖의 select * from 문에서 데이터를 한줄한줄 출력하는 과정에서
{2} select 안의 subquery가 매 데이터 한줄마다 실행되는데
{3} 그 데이터 한 줄의 user_id를 갖는 데이터의 평균 좋아요 값을 subquery에서 계산해서
{4} 함께 출력해준다!
3) From 에 들어가는 Subquery (가장 많이 사용되는 유형!)
From은 언제 사용하면 좋을까요? 내가 만든 Select와 이미 있는 테이블을 Join하고 싶을 때 사용하면 딱이겠죠!
자, 우선 유저 별 좋아요 평균을 먼저 구해볼까요? → checkins 테이블을 user_id로 group by 하면 되겠죠?
select user_id, round(avg(likes),1) as avg_like from checkins group by user_id
자, 이제 여기서 해당 유저 별 포인트를 보고 싶다면? → 그러면, 포인트와 like의 상관정도를 알 수 있겠죠?
select pu.user_id, a.avg_like, pu.point from point_users pu inner join ( select user_id, round(avg(likes),1) as avg_like from checkins group by user_id ) a on pu.user_id = a.user_id
쿼리가 실행되는 순서를 이렇게 상상하면 편해요!
{1} 먼저 서브쿼리의 select가 실행되고,
{2} 이것을 테이블처럼 여기고 밖의 select가 실행!