본문 바로가기
데이터 분석 및 업무 자동화

MySQL 데이터 그룹화하기 - GROUP BY

by 공부머리 2022. 1. 27.
반응형

오늘은 MySQL 데이터 그룹화하기에 대해서 알아보도록 하겠습니다. 


데이터 그룹화하기 (GROUP BY)

데이터 그룹화란 엑셀에서 피벗을 활용하여 원하는 데이터를 그룹화하는 기능과 유사합니다. "고객 등급 별 매출 통계 뽑아주세요", "상품 카테고리 별 실적 통계 뽑아주세요" 등 데이터를 그룹화해서 통계 낼 때 사용됩니다. 컬럼에서 동일한 값을 가지는 로우를 그룹화하는 키워드는 GROUP BY입니다.

 

GROUP BY 특징

  • GROUP BY [컬럼 이름] 형식으로 사용합니다.
  • 주로 그룹 별 데이터를 집계할 때 사용하며, 엑셀의 피벗 기능과 유사합니다.
  • GROUP BY가 쓰인 쿼리의 SELECT 절에는 GROUP BY 대상 컬럼과 그룹 함수만 사용 가능합니다.
    • 만약, GROUP BY 대상 컬럼이 아닌 컬럼을 SELECT 하면, 에러가 발생합니다.
  • 여러 컬럼으로 그룹화도 가능하며, 키워드 뒤에 [컬럼 이름]을 복수 개 입력하면 됩니다.
  • 컬럼 번호로도 그룹화가 가능합니다.
    • 이때, 컬럼 번호는 SELECT 절의 컬럼 이름의 순서를 의미합니다.

 

GROUP BY 쿼리 문법

SELECT [GROUP BY 대상 컬럼 이름], ..., [그룹 함수]

FROM [테이블 이름]

WHERE 조건식

GROUP BY [컬럼 이름];

-> GROUP BY는 WHERE 다음에 위치하게 되며 SELECT 뒤에는 GROUP BY 대상 컬럼 이름과 그룹 함수만 올 수 있습니다.


그룹에 조건 추가 (Having)

가져올 데이터 그룹에 조건을 지정해주는 키워드는 HAVING입니다.

 

HAVING의 특징

  • HAVING 조건식 형식으로 사용합니다.
  • 조건식이 True(참)이 되는 그룹만 선택합니다.
  • HAVING 절의 조건식에는 그룹 함수를 활용합니다.

HAVING 쿼리 문법

SELECT [컬럼 이름],..., [그룹 함수]

FROM [테이블 이름]

WHERE 조건식

GROUP BY [컬럼 이름]

HAVING 조건식;

-> HAVING은 GROUP BY 다음에 위치하게 되며 그룹들 중에서 진짜로 가져오고 싶은 그룹들의 조건을 지정해 줍니다.


다양한 그룹 함수 알아보기 (COUNT, SUM, AVG, MINMAX)


COUNT의 특징

  • 그룹의 값 수를 세는 함수
  • COUNT([컬럼 이름]) 형식으로 SELECT, HAVING 절에서 사용합니다.
    • 집계할 컬럼 이름은 그룹의 기준이 되는 컬럼 이름과 같아도 되고, 같지 않아도 됩니다.
    • COUNT(1)은 하나의 값을 1로 세어주는 표현으로 COUNT 함수에 자주 사용합니다.
  • GROUP BY가 없는 쿼리에서도 사용 가능하며, 이때는 전체 로우에 함수가 적용됩니다.

 

COUNT 쿼리 문법

SELECT [컬럼 이름], ..., COUNT([컬럼 이름])

FROM [테이블 이름]

GROUP BY [컬럼 이름]

HAVING 조건문;


SUM의 특징

  • 그룹의 합을 계산하는 함수
  • SUM([컬럼 이름]) 형식으로 SELECT, HAVING 절에서 사용합니다.
    • 집계할 컬럼 이름은 그룹의 기준이 되는 컬럼 이름과 같아도 되고, 같지 않아도 됩니다.
  • GROUP BY가 없는 쿼리에서도 사용 가능하며, 이때는 전체 로우에 함수가 적용됩니다.

 

SUM 쿼리 문법

SELECT [컬럼 이름], ..., SUM([컬럼 이름])

FROM [테이블 이름]

GROUP BY [컬럼 이름]

HAVING 조건문;

-> 한 가지 팁은 그룹의 기준이 되는 컬럼 이름을 함께 SELECT 해야 의미를 파악할 수 있습니다.


AVG의 특징

  • 그룹의 평균을 계산하는 함수
  • AVG([컬럼 이름]) 형식으로 SELECT, HAVING 절에서 사용합니다.
    • 집계할 컬럼 이름은 그룹의 기준이 되는 컬럼 이름과 같아도 되고, 같지 않아도 됩니다.
  • GROUP BY가 없는 쿼리에서도 사용 가능하며, 이때는 전체 로우에 함수가 적용됩니다.

 

AVG 쿼리 문법

SELECT [컬럼 이름], ..., AVG([컬럼 이름])

FROM [테이블 이름]

GROUP BY [컬럼 이름]

HAVING 조건문;

-> 한 가지 팁은 그룹의 기준이 되는 컬럼 이름을 함께 SELECT 해야 의미를 파악할 수 있습니다.


MIN의 특징

  • 그룹의 최솟값을 계산하는 함수
  • MIN([컬럼 이름]) 형식으로 SELECT, HAVING 절에서 사용합니다.
    • 집계할 컬럼 이름은 그룹의 기준이 되는 컬럼 이름과 같아도 되고, 같지 않아도 됩니다.
  • GROUP BY가 없는 쿼리에서도 사용 가능하며, 이때는 전체 로우에 함수가 적용됩니다.

 

MIN 쿼리 문법

SELECT [컬럼 이름], ..., MIN([컬럼 이름])

FROM [테이블 이름]

GROUP BY [컬럼 이름]

HAVING 조건문;

 

<예시 1>

SELECT type, COUNT(*), COUNT(1), AVG(height), MAX(weight)

FROM pokemon.mypokemon

GROUP BY type;

-> 실행하게 되면 첫 번째 열에는 그룹화한 type 값들이 오게 됩니다. 다음으로 COUNT(*)는 그룹별 전체 로우수를 세어서 결과로 나타냅니다. 다음으로 COUNT(1)은 그룹별 로우를 하나의 값을 1로 치환해서 합을 보여줍니다. 다음은 키의 평균값이 반환됩니다. 마지막으로 몸무게의 최댓값이 반환됩니다.

 

<예시 2>

SELECT type, COUNT(*), COUNT(1), AVG(height), MAX(weight)

FROM pokemon.mypokemon

GROUP BY type;

HAVING COUNT(1) = 2;

-> 실행하게 되면 예시 1의 결괏값에서 COUNT(1) = 2의 조건을 만족하는 그룹만 출력됩니다.


쿼리 실행 순서 알아보기

MySQL 쿼리문의 6가지 핵심 쿼리 키워드를 정리해보겠습니다.

키워드 문법 작성 순서 실행 순서
SELECT SELECT [컬럼 이름] 1 5
FROM FROM [테이블 이름] 2 1
WHERE WHERE 조건식 3 2
GROUP BY GROUP BY [컬럼 이름] 4 3
HAVING HAVING 조건식 5 4
ORDER BY ORDER BY [컬럼 이름] 6 6

mypokemon
number name type height weight
10 caterpie bug 0.3 2.9
25 pikache electric 0.4 6
26 raichu electric 0.8 30
125 electabuzz electric 1.1 30
133 eevee normal 0.3 6.5
137 porygon normal 0.8 36.5
152 chikorita grass 0.9 6.4
153 bayleef grass 1.2 15.8
172 pichu electric 0.3 2
470 leafeon grass 1 25.5

위와 같은 데이터 베이스가 있을 때 아래와 같은 쿼리문을 작성하여 어떠한 순서로 실행이 진행되는지 단계별로 살펴보겠습니다.

 

SELECT type, COUNT(1), MAX(weight) -> 실행 순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행 순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

 


SELECT type, COUNT(1), MAX(weight) -> 실행순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

-> 실행순서 1은 pokemon이라는 데이터 베이스에서 mypokemon이라는 테이블을 불러오는 쿼리문입니다.


SELECT type, COUNT(1), MAX(weight) -> 실행순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

-> 실행 순서 2는 WHERE절에서 name열에서 a를 포함하는 열을 가져오라는 쿼리문입니다. 실행하면 아래 테이블과 같이 name에 a를 포함하는 로우만 남게 됩니다. 

mypokemon
number name type height weight
10 caterpie bug 0.3 2.9
25 pikache electric 0.4 6
26 raichu electric 0.8 30
125 electabuzz electric 1.1 30
152 chikorita grass 0.9 6.4
153 bayleef grass 1.2 15.8
470 leafeon grass 1 25.5

SELECT type, COUNT(1), MAX(weight) -> 실행순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

-> 실행순서 3은 type을 기준으로 그룹화를 합니다. 그룹화를 하면 아래 테이블과 같이 정리됩니다.

mypokemon
type number name height weight
bug 10 caterpie 0.3 2.9
electric 25 pikachu 0.4 6
26 raichu 0.8 30
125 electabuzz 1.1 30
grass 152 chikorita 0.9 6.4
153 bayleef 1.2 15.8
470 leafeon 1 25.5

SELECT type, COUNT(1), MAX(weight) -> 실행순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

-> 실행 순서 4를 진행하면 각 그룹별 height의 max값이 1이 넘는 그룹만 남습니다. 해당하는 그룹은 electric과 grass 뿐입니다. 아래와 같은 데이터만 남게 됩니다.

mypokemon
type number name height weight
electric 25 pikachu 0.4 6
26 raichu 0.8 30
125 electabuzz 1.1 30
grass 152 chikorita 0.9 6.4
153 bayleef 1.2 15.8
470 leafeon 1 25.5

SELECT type, COUNT(1), MAX(weight) -> 실행 순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행 순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY3: -> 실행순서 6

-> 실행 순서 5를 거치게 되면 각그룹별 로우값을 1로 하여 합을한 결과가 나오고 weight의 최대값이 결과로 반환됩니다.

type COUNT(1) MAX(weight)
electric 3 3
grass 3 25.5

SELECT type, COUNT(1), MAX(weight) -> 실행순서 5

FROM pokemon.mypokemon -> 실행순서 1

WHERE name LIKE '%a%' -> 실행 순서 2

GROUP BY type -> 실행순서 3

HAVING MAX(height) > 1 -> 실행순서 4

ORDER BY 3: -> 실행순서 6

-> 실행순서 6을 거치게 되면 3번째 열인 MAX(weight)의 오름차순으로 정렬합니다. 결괏값은 아래 테이블과 같습니다.

type COUNT(1) MAX(weight)
grass 3 25.5
electric 3 30

이상으로 MySQL에서 데이터 그룹화하는 방법에 대해서 알아보았습니다.

반응형

댓글