공통 쿼리 재사용을 고려한 랜덤 추출 쿼리 작성 방법 (Oracle + MyBatis)

최근 프로젝트에서 조건에 맞는 카테고리 중 랜덤으로 하나씩 상품을 뽑고, 조건에 맞는 나머지 상품을 추가로 추출하여 총 n개를 만드는 쿼리를 작성할 일이 있었다.
단순히, union all 로 처리할 수 있지만, 중복 상품, 조건 필터링, MyBatis와의 연동 등을 고려하다 보니 쿼리가 점점 길어졌다.
이 글에서는 Oracle에서 중복을 피하면서 효율적인 쿼리를 작성하고, MyBatis XML에서 공통 쿼리를 재활용하는 방법을 소개한다.
처음 작성한 쿼리
처음에 간단하게 각각 하나씩 뽑고 UNION ALL 로 붙이면 될 줄 알았다.
하지만 이 방식은 조건에 맞는 데이터를 추출하면서 쿼리 중복과 중복된 결과 처리 문제가 발생했다.
반복되는 UNION ALL 쿼리를 효율적으로 관리하고, MyBatis에서 공통 SQL을 재사용하는 방법을 정리해봤다.
SELECT prd_no FROM ( SELECT prd_no FROM A WHERE category = 1 AND category_code = '01' ORDER BY DBMS_RANDOM.RANDOM ) WHERE ROWNUM = 1 UNION ALL ... (category 2, 3, 4)
문제 상황
불편한 점
- prd_no 중복 발생 시 정확한 카운트 문제
- 중복 쿼리 반복 -> 가독성 저하
- 유지보수 어려움
- MyBatis 에서 동일 SQL 을 2~3번 반복 사용함
해결: 공통 SQL 분리 (<sql> 재사용)
같은 로직을 3번 박복하는 대신, <sql> 로 분리하여 한 번만 작성하고 재사용하니 훨씬 깔끔하고 유지보수도 쉬워졌다.
Oracle
WITH sample AS ( -- 중복된 부분 미리 정의 ) SELECT DISTINCT prd_no FROM sample UNION ALL ...
MyBatis
<sql id="sample"> -- 카테고리별 랜덤 추출 </sql> <select id="getPrdNoList" resultType="Long"> SELECT DISTINCT prd_no FROM ( <include refid="sample"/> UNION ALL SELECT prd_no FROM ... ) </select>
배운 점 / 팁 정리
- Oracle 에선 WITH, MyBatis 에선 <sql> + <include> 조합을 활용하자.
- 중복된 prd_no 가 생길 수 있으니, DISTINCT, NOT IN 으로 필터링
- n개를 맞추려면 실제 뽑힌 상품 개수를 기준으로 계산해야 함
- 쿼리가 복잡해질수록 공통 쿼리 분리 습관이 필요하다.
'IT' 카테고리의 다른 글
Dynamic Programming (DP) : 작은 문제의 답을 조합해 큰 문제를 푼다. (0) | 2025.04.13 |
---|---|
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법 (0) | 2025.03.30 |
웹 브라우저 요청 흐름 (0) | 2025.01.06 |
RxParallelRunner 소개 (0) | 2024.12.02 |
Internal, external gateway 에 대해서 (1) | 2024.11.25 |
댓글
이 글 공유하기
다른 글
-
Dynamic Programming (DP) : 작은 문제의 답을 조합해 큰 문제를 푼다.
Dynamic Programming (DP) : 작은 문제의 답을 조합해 큰 문제를 푼다.
2025.04.13 -
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법
2025.03.30 -
웹 브라우저 요청 흐름
웹 브라우저 요청 흐름
2025.01.06 -
RxParallelRunner 소개
RxParallelRunner 소개
2024.12.02
댓글을 사용할 수 없습니다.