개요
MySQL에서 테이블의 전체 데이터가 아니라 마지막 50개 항목 가운데 임의의 5개 행만 조회해야 하는 경우가 있습니다. 이럴 때는 서브쿼리와 함께 ORDER BY RAND()를 사용하면 간단하게 해결할 수 있습니다.
핵심 아이디어는 다음과 같습니다.
- 먼저 내부 서브쿼리에서
ORDER BY ... DESC와LIMIT 50으로 최신(마지막) 50개 행을 추출합니다. - 그 결과를 외부 쿼리에서
ORDER BY RAND()로 무작위 정렬한 뒤LIMIT 5로 5개 행만 가져옵니다.
1. 예제 테이블 생성
먼저 실습에 사용할 테이블을 만들어 보겠습니다.
mysql> create table DemoTable1853
(
UserId int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(UserId)
);
Query OK, 0 rows affected (0.00 sec)2. 샘플 데이터 삽입
insert 명령으로 여러 개의 레코드를 한 번에 추가합니다. 값 없이 ()만 나열하면 AUTO_INCREMENT 컬럼에 순차적인 번호가 자동으로 입력됩니다.
mysql> insert into DemoTable1853 values(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(); Query OK, 58 rows affected (0.00 sec) Records: 58 Duplicates: 0 Warnings: 0
3. 저장된 데이터 확인
select 문으로 테이블의 모든 레코드를 조회합니다.
mysql> select * from DemoTable1853;
실행 결과는 다음과 같습니다. UserId가 1부터 58까지 총 58개 행이 저장되어 있습니다.
+--------+ | UserId | +--------+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 10 | | 11 | | 12 | | 13 | | 14 | | 15 | | 16 | | 17 | | 18 | | 19 | | 20 | | 21 | | 22 | | 23 | | 24 | | 25 | | 26 | | 27 | | 28 | | 29 | | 30 | | 31 | | 32 | | 33 | | 34 | | 35 | | 36 | | 37 | | 38 | | 39 | | 40 | | 41 | | 42 | | 43 | | 44 | | 45 | | 46 | | 47 | | 48 | | 49 | | 50 | | 51 | | 52 | | 53 | | 54 | | 55 | | 56 | | 57 | | 58 | +--------+ 58 rows in set (0.00 sec)
4. 마지막 50개 항목에서 임의의 5개 행 선택하기
이제 핵심 쿼리입니다. 내부 서브쿼리로 마지막 50개 행을 먼저 걸러낸 후, 그 안에서 무작위로 5개 행만 선택합니다.
mysql> select tbl.*
from (select tbl1.*
from DemoTable1853 tbl1
order by UserId DESC
LIMIT 50
) tbl
order by rand()
limit 5;실행 결과는 다음과 같습니다. UserId 9~58 범위(마지막 50개 항목)에 속하는 행들이 무작위로 5개 반환된 것을 확인할 수 있습니다.
+--------+ | UserId | +--------+ | 19 | | 24 | | 43 | | 36 | | 48 | +--------+ 5 rows in set (0.00 sec)
정리 및 참고 사항
이 방식은 두 단계로 동작합니다. 첫 번째 서브쿼리가 UserId DESC 정렬과 LIMIT 50을 통해 최근 50개 행을 확정하고, 두 번째 외부 쿼리가 그 결과 집합에 대해서만 RAND()로 무작위 추출을 수행합니다. 덕분에 전체 테이블이 아니라 원하는 범위 안에서만 랜덤 샘플링이 가능합니다.
다만 ORDER BY RAND()는 대상 행 수가 많아지면 성능이 떨어질 수 있으므로, 데이터 규모가 큰 테이블에서는 서브쿼리로 범위를 좁힌 후 적용하는 것이 좋습니다. 또한 실행할 때마다 결과가 달라지는 것이 정상이며, 매번 고정된 결과가 필요하다면 별도의 시드(seed) 기반 난수 처리를 고려해야 합니다.