MySQL에서 GROUP BY가 반환한 행 수를 기준으로 그룹화하는 방법
MySQL에서 각 이름이 몇 번 등장했는지 세고, 그 등장 횟수(행 수)를 기준으로 다시 그룹화하고 싶을 때가 있습니다. 이럴 때 GROUP_CONCAT() 함수를 활용하면 손쉽게 해결할 수 있습니다.
개념을 이해하기 위해 먼저 예제 테이블을 만들어 보겠습니다.
1. 테이블 생성
아래 쿼리로 groupByDemo 테이블을 생성합니다.
mysql> create table groupByDemo
-> (
-> Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Name varchar(100)
-> );
Query OK, 0 rows affected (1.31 sec)2. 샘플 데이터 삽입
INSERT 명령어를 사용해 여러 개의 레코드를 추가합니다.
mysql> insert into groupByDemo(Name) values('John');
Query OK, 1 row affected (0.19 sec)
mysql> insert into groupByDemo(Name) values('Carol');
Query OK, 1 row affected (0.14 sec)
mysql> insert into groupByDemo(Name) values('Carol');
Query OK, 1 row affected (0.10 sec)
mysql> insert into groupByDemo(Name) values('Bob');
Query OK, 1 row affected (0.24 sec)
mysql> insert into groupByDemo(Name) values('Bob');
Query OK, 1 row affected (0.23 sec)
mysql> insert into groupByDemo(Name) values('Bob');
Query OK, 1 row affected (0.17 sec)
mysql> insert into groupByDemo(Name) values('John');
Query OK, 1 row affected (0.16 sec)
mysql> insert into groupByDemo(Name) values('John');
Query OK, 1 row affected (0.07 sec)
mysql> insert into groupByDemo(Name) values('John');
Query OK, 1 row affected (0.11 sec)
mysql> insert into groupByDemo(Name) values('Sam');
Query OK, 1 row affected (0.17 sec)
mysql> insert into groupByDemo(Name) values('Carol');
Query OK, 1 row affected (0.19 sec)3. 전체 레코드 조회
SELECT 문으로 테이블의 모든 레코드를 확인합니다.
mysql> select *from groupByDemo;
실행 결과는 다음과 같습니다.
+----+-------+ | Id | Name | +----+-------+ | 1 | John | | 2 | Carol | | 3 | Carol | | 4 | Bob | | 5 | Bob | | 6 | Bob | | 7 | John | | 8 | John | | 9 | John | | 10 | Sam | | 11 | Carol | +----+-------+ 11 rows in set (0.00 sec)
4. 행 수(Counter)를 기준으로 그룹화
이제 핵심 쿼리입니다. 서브쿼리에서 각 이름별 등장 횟수를 COUNT로 집계한 뒤, 외부 쿼리에서 그 횟수를 기준으로 다시 GROUP BY를 수행하고 GROUP_CONCAT()으로 같은 횟수를 가진 이름들을 하나로 합칩니다.
mysql> SELECT Counter, GROUP_CONCAT(Name SEPARATOR ', ') as AllName
-> FROM (SELECT Name, COUNT(Name) as Counter
-> FROM groupByDemo
-> GROUP BY Name) tbl
-> GROUP BY Counter
-> ORDER BY Counter DESC;실행 결과는 다음과 같습니다.
+---------+------------+ | Counter | AllName | +---------+------------+ | 4 | John | | 3 | Carol, Bob | | 1 | Sam | +---------+------------+ 3 rows in set (0.00 sec)
결과 해석
- John은 4번 등장하여 단독으로 '4회' 그룹에 속합니다.
- Carol과 Bob은 각각 3번씩 등장하여 같은 그룹으로 묶였습니다.
- Sam은 1번만 등장하여 '1회' 그룹에 해당합니다.
이처럼 서브쿼리와 GROUP_CONCAT()을 조합하면, GROUP BY로 집계된 행 수를 기준으로 데이터를 유연하게 재그룹화할 수 있습니다.