com.querydsl.jpa.JPAExpressions사용
JPAExpressions.select()
.from()
멤버 중 나이가 가장 많은 멤버들을 조회!
where 절에 서브쿼리를 사용해서 회원 나이 중 최댓값을 조회해온다.
/**
* 서브 쿼리 - eq 사용
*/
@Test
public void subQuery() throws Exception {
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq( // 메인 쿼리: 멤버의 나이가 최댓값인 회원 조회
// 서브쿼리: member의 나이의 최댓값 조회
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
assertThat(result).extracting("age")
.containsExactly(40);
}

멤버 중 나이가 평균값보다 크거나 같은 멤버들을 조회!
where 절에 서브쿼리를 사용해서 회원 나이의 평균 값을 조회해온다.
/**
* 서브 쿼리 - goe 사용
*/
@Test
public void subQueryGoe() throws Exception {
QMember memberSub = new QMember("memberSub"); // 서브쿼리 테이블명은 메인쿼리 테이블명과 달라야하기때문
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.goe( // 메인 쿼리: 멤버의 나이가 평균값보다 크거나 같은 멤버 조회
// 서브쿼리: member의 나이의 평균값 조회
JPAExpressions
.select(memberSub.age.avg())
.from(memberSub)
))
.fetch();
assertThat(result).extracting("age")
.containsExactly(30, 40);
}

멤버 중 나이가 10살보다 많은 멤버들을 조회!
where 절에 서브쿼리를 사용해서 10살 보다 많은 회원의 나이들을 조회해온다.
/**
* 서브 쿼리 - in
*/
@Test
public void subQueryIn() throws Exception {
QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.in( // in 사용) 메인 쿼리: 멤버의 나이 10살보다 많은 멤버 조회
// 서브쿼리: 10살보다 많은 나이값들 조회
JPAExpressions
.select(memberSub.age)
.from(memberSub)
.where(memberSub.age.gt(10))
))
.fetch();
assertThat(result).extracting("age")
.containsExactly(20, 30, 40);
}

멤버의 이름과 유저의 평균 나이를 select
import com.querydsl.jpa.JPAExpressions; // JPAExpression static import
@Test
public void selectSubQuery() throws Exception {
QMember memberSub = new QMember("memberSub");
List<Tuple> result = queryFactory
.select(member.username,
// 서브 쿼리: 유저 평균 나이 조회, JPAExpressions static import
select(memberSub.age.avg())
.from(memberSub))
.from(member)
.fetch();
for (Tuple tuple : result) {
System.out.println("tuple = " + tuple);
}
}


member.username과 멤버의 평균나이가 같이 select되어 출력되는 것을 확인
JPA 표준 스펙 : where절 서브쿼리만 가능
하이버네이트 구현체 사용 : select 절 서브쿼리 지원
JPA JPQL 서브쿼리의 한계점으로 from절의 서브쿼리는 지원하지 않는다.
1번부터 순차적으로 시도
데이터 그룹핑(groupby), 필터링(where..)해서 조회
only 데이터 퍼올리는 것에 집중 -> from절 쿼리 줄일 수 있고, 복잡한 쿼리 많이 줄일 수 있음
데이터 가공
예) 날짜 이쁘게 포맷하는 건 애플리케이션 단에서 처리
실시간 트래픽 중요 - 한방 쿼리 선호
백단 관리자(ADMIN) - 한방 쿼리 굳이 선호하지는 않음
참고)
SQL AntiPatterns 책 추천해주셨다!