Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

MySQL에서 그룹별로 묶은 뒤 무작위로 정렬하는 방법

MySQL에서 데이터를 특정 컬럼 기준으로 그룹화하면서도 그룹의 순서는 매번 무작위로 섞고 싶을 때가 있습니다. 예를 들어 같은 값을 가진 행들은 서로 붙여서 보여주되, 어떤 그룹이 먼저 나올지는 실행할 때마다 달라지도록 하는 것이죠. 이 글에서는 서브쿼리와 RAND() 함수를 활용해 이를 구현하는 방법을 단계별로 살펴봅니다.

1. 예제 테이블 생성하기

먼저 실습에 사용할 테이블을 만들어 보겠습니다.

mysql> create table DemoTable
    (
    Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Value char(1)
    );
Query OK, 0 rows affected (0.66 sec)

2. 샘플 데이터 삽입하기

INSERT 문을 사용해 몇 개의 레코드를 추가합니다.

mysql> insert into DemoTable(Value) values('X');
Query OK, 1 row affected (0.20 sec)

mysql> insert into DemoTable(Value) values('Y');
Query OK, 1 row affected (0.09 sec)

mysql> insert into DemoTable(Value) values('X');
Query OK, 1 row affected (0.30 sec)

mysql> insert into DemoTable(Value) values('X');
Query OK, 1 row affected (0.07 sec)

mysql> insert into DemoTable(Value) values('Y');
Query OK, 1 row affected (0.17 sec)

mysql> insert into DemoTable(Value) values('Z');
Query OK, 1 row affected (0.13 sec)

mysql> insert into DemoTable(Value) values('Z');
Query OK, 1 row affected (0.11 sec)

3. 저장된 레코드 확인하기

SELECT 문으로 테이블의 전체 데이터를 조회합니다.

mysql> select *from DemoTable;

실행 결과는 다음과 같습니다.

+----+-------+
| Id | Value |
+----+-------+
| 1  | X     |
| 2  | Y     |
| 3  | X     |
| 4  | X     |
| 5  | Y     |
| 6  | Z     |
| 7  | Z     |
+----+-------+
7 rows in set (0.00 sec)

4. 그룹화하면서 무작위로 정렬하는 쿼리

핵심 아이디어는 간단합니다. 먼저 서브쿼리에서 Value 기준으로 그룹화한 뒤 각 그룹에 RAND() 값 하나를 부여하고, 이 난수를 기준으로 외부 쿼리를 정렬하는 것입니다. 이렇게 하면 같은 그룹에 속한 행들은 함께 유지되면서 그룹 자체의 순서만 무작위로 바뀌게 됩니다.

Case 1 − 그룹별로 묶되 무작위 순서로 정렬하는 쿼리는 다음과 같습니다.

mysql> select DemoTable.*
    from DemoTable join
    (
    select Value, rand() as `random_Value`
    from DemoTable
    group by Value
    ) tbl2
    on DemoTable.Value = tbl2.Value
order by tbl2.`random_Value`;

실행 결과는 다음과 같습니다.

+----+-------+
| Id | Value |
+----+-------+
| 6  | Z     |
| 7  | Z     |
| 1  | X     |
| 3  | X     |
| 4  | X     |
| 2  | Y     |
| 5  | Y     |
+----+-------+
7 rows in set (0.00 sec)

결과를 보면 X, Y, Z 그룹 내부의 행들은 서로 인접해 있지만, 그룹의 등장 순서(Z → X → Y)는 무작위로 결정된 것을 확인할 수 있습니다.

5. 쿼리 재실행으로 무작위성 확인하기

Case 2 − 무작위 정렬이 제대로 작동하는지 확인하기 위해 동일한 쿼리를 한 번 더 실행해 보겠습니다.

mysql> select DemoTable.*
    from DemoTable join
    (
    select Value, rand() as `random_Value`
    from DemoTable
    group by Value
    ) tbl2
    on DemoTable.Value = tbl2.Value
order by tbl2.`random_Value`;

이번에는 그룹 순서가 달라진 것을 볼 수 있습니다.

+----+-------+
| Id | Value |
+----+-------+
| 2  | Y     |
| 5  | Y     |
| 6  | Z     |
| 7  | Z     |
| 1  | X     |
| 3  | X     |
| 4  | X     |
+----+-------+
7 rows in set (0.00 sec)

정리

이 기법의 핵심은 다음과 같습니다.

- 서브쿼리에서 GROUP BY로 그룹을 만들고, 각 그룹에 RAND()로 생성한 난수를 할당합니다.
- 메인 쿼리는 원본 테이블과 이 서브쿼리를 조인하여, 그룹 단위로 부여된 난수를 기준으로 ORDER BY를 수행합니다.
- 덕분에 그룹 내부의 행 순서는 유지되면서, 그룹 전체의 배치 순서만 실행 시점마다 무작위로 변경됩니다.

퀴즈 항목 셔플, 추천 콘텐츠 랜덤 노출처럼 그룹 단위 무작위 정렬이 필요한 다양한 상황에서 유용하게 활용할 수 있는 패턴입니다.