테이블 생성
먼저 실습에 사용할 테이블을 만들어 보겠습니다.
mysql> create table DemoTable
-> (
-> StudentId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentMarks int
-> );
Query OK, 0 rows affected (0.58 sec)
샘플 데이터 삽입
INSERT 명령으로 레코드를 추가합니다. 그룹화 효과를 확인할 수 있도록 동일한 점수(98, 78)를 가진 중복 레코드도 일부러 함께 넣었습니다.
mysql> insert into DemoTable(StudentMarks) values(98); Query OK, 1 row affected (0.11 sec) mysql> insert into DemoTable(StudentMarks) values(98); Query OK, 1 row affected (0.10 sec) mysql> insert into DemoTable(StudentMarks) values(78); Query OK, 1 row affected (0.10 sec) mysql> insert into DemoTable(StudentMarks) values(78); Query OK, 1 row affected (0.29 sec) mysql> insert into DemoTable(StudentMarks) values(45); Query OK, 1 row affected (0.10 sec) mysql> insert into DemoTable(StudentMarks) values(56); Query OK, 1 row affected (0.09 sec)
저장된 데이터 확인
SELECT 문으로 테이블의 전체 레코드를 조회합니다.
mysql> select *from DemoTable;
실행 결과는 다음과 같습니다.
+-----------+--------------+ | StudentId | StudentMarks | +-----------+--------------+ | 1 | 98 | | 2 | 98 | | 3 | 78 | | 4 | 78 | | 5 | 45 | | 6 | 56 | +-----------+--------------+ 6 rows in set (0.00 sec)
그룹을 유지한 채 무작위 정렬하기
행마다 완전히 섞는 것이 아니라, 같은 점수끼리 묶인 상태에서 그룹 단위의 순서만 무작위로 바꾸고 싶다면 아래 쿼리처럼 RAND()에 시드 값을 활용하면 됩니다.
mysql> select *from DemoTable order by rand(StudentMarks*100*RAND());
실행 결과를 보면 점수가 98점인 두 레코드(StudentId 1번, 2번)가 여전히 인접한 채 그룹으로 유지되면서, 전체 행의 순서만 무작위로 섞인 것을 확인할 수 있습니다.
+-----------+--------------+ | StudentId | StudentMarks | +-----------+--------------+ | 3 | 78 | | 6 | 56 | | 5 | 45 | | 4 | 78 | | 1 | 98 | | 2 | 98 | +-----------+--------------+ 6 rows in set (0.00 sec)
동작 원리와 참고 사항
여기서 핵심은 MySQL에서 RAND()에 인자를 전달하면 해당 값이 시드(seed)로 사용되어 결정적인 의사 난수를 반환한다는 점입니다. 위 쿼리에서는 StudentMarks * 100 * RAND()를 시드로 사용하기 때문에, 동일한 점수를 가진 행들이 서로 연관된 정렬 키를 갖게 되고 그 결과 그룹이 흩어지지 않고 유지됩니다.
다만 ORDER BY RAND()는 모든 행에 대해 난수를 계산한 후 정렬을 수행하기 때문에, 데이터 양이 많은 테이블에서는 성능 부담이 커질 수 있습니다. 대량 데이터 환경에서는 임시 테이블 활용이나 애플리케이션 단계에서의 셔플 처리 등 다른 방식을 함께 고려하는 것이 좋습니다.