서브쿼리

학습 페이지

서브쿼리는 기본적으로 다음의 패키지를 사용한다.

com.querydsl.jpa.JPAExpressions

실제로 사용해보자.

where절 서브쿼리

    /**
     *  나이가 가장 많은 회원 조회
     */
    @Test
    public void subQuery() {
        //서브쿼리는 별칭이 겹치면 안된다.
        QMember memberSub = new QMember("memberSub");

        List<Member> fetch = queryFactory
                .selectFrom(member)
                .where(member.age.eq(
                        JPAExpressions
                                .select(memberSub.age.max())
                                .from(memberSub)
                ))
                .fetch();

        assertThat(fetch).extracting("age").containsExactly(40);
    }

여기서 중요한건 만약 같은 테이블 대상으로 서브쿼리를 날릴거라면 서브쿼리내 별칭은 메인쿼리의 별칭과 동일해서는 안된다는 것이다.

image.png

생성된 jpql을 보면 위와 같다.

    @Test
    public void subQueryIn() {
        //서브쿼리는 별칭이 겹치면 안된다.
        QMember memberSub = new QMember("memberSub");

        List<Member> fetch = queryFactory
                .selectFrom(member)
                .where(member.age.in(
                        JPAExpressions
                                .select(memberSub.age)
                                .from(memberSub)
                                .where(memberSub.age.gt(10))

                ))
                .fetch();

        assertThat(fetch).extracting("age").containsExactly(20, 30, 40);
    }

image.png

생성된 jpql의 모습

서브쿼리는 select절에서도 가능하다.

select절 서브쿼리

    @Test
    public void selectSubQuery() {
        QMember memberSub = new QMember("memberSub");

        List<Tuple> fetch = queryFactory.select(member.username,
                        JPAExpressions
                                .select(memberSub.age.avg())
                                .from(memberSub))
                .from(member)
                .fetch();

        for(Tuple tuple : fetch) {
            System.out.println("tuple = " + tuple);
        }
    }

💡 참고로 JPAExpressions 은 스태틱 임포트가 가능하다.