개요
MySQL에서 레코드를 조회할 때 특정 값은 항상 맨 앞에 고정하고, 나머지 값들 중 일부만 무작위로 가져오고 싶은 경우가 있습니다. 이럴 때 ORDER BY RAND()와 LIMIT를 함께 사용하면 간단하게 해결할 수 있습니다.
핵심 아이디어는 ORDER BY 절에서 조건식 (컬럼명='값')의 결과를 활용하는 것입니다. MySQL에서는 조건이 참이면 1, 거짓이면 0을 반환하므로, 내림차순(DESC)으로 정렬하면 해당 조건을 만족하는 행이 자동으로 맨 앞에 오게 됩니다.
1. 테이블 생성
먼저 예제에 사용할 테이블을 만들어 보겠습니다.
mysql> create table DemoTable1426
-> (
-> FirstName varchar(20)
-> );
Query OK, 0 rows affected (0.59 sec)
2. 데이터 삽입
INSERT 문을 사용해 몇 개의 레코드를 추가합니다.
mysql> insert into DemoTable1426 values('John');
Query OK, 1 row affected (0.17 sec)
mysql> insert into DemoTable1426 values('Adam');
Query OK, 1 row affected (0.10 sec)
mysql> insert into DemoTable1426 values('Robert');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable1426 values('David');
Query OK, 1 row affected (0.12 sec)
mysql> insert into DemoTable1426 values('Sam');
Query OK, 1 row affected (0.13 sec)3. 전체 레코드 확인
SELECT 문으로 테이블의 모든 레코드를 조회해 보겠습니다.
mysql> select * from DemoTable1426;
실행 결과는 다음과 같습니다.
+-----------+
| FirstName |
+-----------+
| John |
| Adam |
| Robert |
| David |
| Sam |
+-----------+
5 rows in set (0.00 sec)
4. 특정 이름 고정 + 나머지 무작위 정렬 쿼리
이제 'Robert'라는 이름을 항상 첫 번째로 고정하고, 나머지 값들은 무작위로 섞어서 상위 3개만 출력하는 쿼리입니다.
mysql> select * from DemoTable1426 order by (FirstName='Robert') desc,RAND()
-> limit 3;
실행 결과는 다음과 같습니다.
+-----------+
| FirstName |
+-----------+
| Robert |
| Adam |
| David |
+-----------+
3 rows in set (0.52 sec)
동작 원리 설명
이 쿼리가 작동하는 원리를 살펴보면 다음과 같습니다.
① 조건식 평가: (FirstName='Robert')는 해당 행이 'Robert'이면 1, 아니면 0을 반환합니다.
② 우선 정렬: DESC로 내림차순 정렬하기 때문에 값이 1인 행(Robert)이 항상 가장 먼저 위치합니다.
③ 무작위 정렬: 조건식 값이 동일한 나머지 행들은 두 번째 정렬 기준인 RAND()에 의해 매번 실행할 때마다 다른 순서로 배치됩니다.
④ 결과 제한: 마지막으로 LIMIT 3이 전체 결과 중 상위 3개 행만 반환하도록 제한합니다.
주의 사항
ORDER BY RAND()는 모든 행에 대해 난수를 계산한 후 정렬하기 때문에, 레코드 수가 많은 대용량 테이블에서는 성능 저하가 발생할 수 있습니다. 소규모 데이터셋에는 적합하지만, 대용량 테이블에서는 서브쿼리나 별도의 랜덤 컬럼을 활용하는 방식을 고려하는 것이 좋습니다.