반응형
JPA 게시글은 대부분 인프런의 김영한님의 강의인 '자바 ORM 표준 JPA 프로그래밍' 기반으로 내용을 정리했습니다.
서브 쿼리
- 일반적인 SQL에서의 서브쿼리와 똑같다.
- 나이가 평균보다 많은 회원
select m from Member m
where m.age > (select avg(m2.age) from Member m2)
상위에서 조회한 Member m을 서브쿼리(괄호 부분)까지 끌고 오지 않았다. 이런 식으로 작성해야 성능에 더 좋으니 참고하자.
- 한 건이라도 주문한 고객
select m from Member m
where (select count(o) from Order o where m = o.member) > 0
위 예제는 상위에서 조회한 Member m을 서브쿼리까지 끌고왔다. 이런 경우에는 성능이 잘 나오지 않는다.
서브 쿼리 지원 함수
- [NOT] EXISTS (subquery) : 서브쿼리에 결과가 존재하면 참
- {ALL | ANY | SOME} (subquery)
- ALL : 모두 만족하면 참
- ANY, SOM : 같은 의미, 조건을 하나라도 만족하면 참
- [NOT] IN (subquery) : 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참
서브 쿼리 - 예제
- 팀 A 소속인 회원
select m from Member m
where exists (select t from m.team t where t.name = '팀A')
위 예제는 서브 쿼리에서 가져온 '팀A'가 Member m 객체에 존재하냐, 하지 않냐를 따지며, 존재하면 참이라 참인 객체들을 모두 가져온다.
- 전체 상품 각각의 재고보다 주문량이 많은 주문들
select o from Order o
where o.orderAmount > ALL (select p.stockAmount from Product p)
stockAmount의 양이 o.orderAmount의 양보다 적은 Order o 객체들을 가져온다.
- 어떤 팀이든 팀에 소속된 회원
select m from Member m
where m.team = ANY (select t from Team t)
서브 쿼리로 가져온 Team과 Member 객체의 Team이 있으면, 즉 Member가 Team에 소속되어 있으면 참이다.
JPA 서브 쿼리 한계
- JPA는 WHERE, HAVING 절에서만 서브 쿼리 사용 가능하다.
- SELECT 절에도 가능하다(하이버네이트에서 지원)
String query = "select (select avg(m1.age) from Member m1 ) as avgAge
from Member m left join Team t on m.username = t.name";
JPA 표준 스펙에서 제공하는 기능은 아니고 하이버네이트에서 지원하는 기능이다.
- FROM 절(인라인 뷰)의 서브 쿼리는 현재 JPQL에서 불가능하다.
- 대신 조인으로 풀 수 있으면 풀어서 해결하면 된다.
- 조인으로도 해결이 안될 경우에 네이티브 쿼리를 사용하거나, 쿼리를 분해해서 따로 날려서 그 쿼리들을 다시 조립하는 방식이 있다. 그래도 제일 좋은 방법은 조인으로 해결하기이긴 하다.
반응형