본문 바로가기
내가 배운 것들/문제 해결

[QueryDSL/MySQL] QueryDSL로 MySQL에서 랜덤한 레코드 가져오기

by Zabee52 2021. 12. 22.

QueryDSL/MySQL

 

 

Does Querydsl not support rand()?

I want to make SQL look like: select b from Book b order by rand() how convert that query to Querydsl query? Is it not supported by Querydsl? If you know the way to support this query, please a...

stackoverflow.com

QueryDSL에서 orderby로 랜덤한 레코드를 가져올 땐 NumberExpression.random()을 사용한다.

근데 MySQL에서는 QueryDSL의 NumberExpression.random() 기능을 사용할 수 없다.

이건 엄밀히 따지면 트러블은 아니다. 그냥 MySQL이 해당 기능을 지원하지 않을 뿐이다.

지원 가능하도록 JPQLTemplates를 튜닝해주면 된다.

참고로 이 기능은 인덱싱이 통하지 않기 때문에 매우 무겁게 작동한다.

레코드가 많다면 인덱싱을 위한 편법을 사용해줘야 할 수도 있다.

 

[MySql] ORDER BY RAND() 튜닝

A회사에서 멤버쉽 가입 고객에 한하여 추첨을 통해 소정의 상품을 지급하려고 합니다. 고객 수는 1000만명...

blog.naver.com

public class MySqlJpaTemplates extends JPQLTemplates{

    public static finalMySqlJpaTemplatesDEFAULT = new MySqlJpaTemplates();

    public MySqlJpaTemplates() {
        this(DEFAULT_ESCAPE);
        add(Ops.MathOps.RANDOM, "rand()");
        add(Ops.MathOps.RANDOM2, "rand({0})");
    }

    public MySqlJpaTemplates(charescape) {
        super(escape);
    }
}

적용예

private List<Quiz> randomQuizPick(int count) {
        // count 만큼의 레코드를 랜덤하게 받아오는 구문
        // MySqlJpaTemplates.DEFAULT : NumberExpression.random().asc()를 MySQL에서 사용 가능하도록
        // 튜닝한 템플릿.
        JPAQuery<Quiz> query = new JPAQuery<>(entityManager, MySqlJpaTemplates.DEFAULT);
        QQuiz qQuiz = new QQuiz("quiz");

        List<Quiz> quizList = query.from(qQuiz)
                .orderBy(NumberExpression.random().asc())
                .limit(count)
                .fetch();

        return quizList;
    }

댓글