PostgreSQL / SQL Basics / 1.5 Aggregation and Grouping
1.5Aggregation and Grouping
GROUP BY와 집계 함수를 통해 많은 데이터를 그룹으로 묶고 요약된 정보를 얻을 수 있다.
많은 데이터를 그룹으로 묶고 요약된 정보를 얻고 싶을 때 사용하는 것이 GROUP BY
와 집계 함수(Aggregate Functions)이다.
Grouping vs Aggregates
개념 | 설명 |
---|---|
Grouping | 여러 개의 row를 그룹으로 묶어서 중복을 없애고 보기 좋게 줄이는 작업 |
Aggregates | 그룹 내의 값들을 하나의 값으로 요약하는 함수들(ex: 합계, 평균) |
Grouping
GROUP BY
키워드를 사용해 여러 행을 그룹으로 묶는다.- 보통 아래의 Aggregate Functions와 함께 쓴다.
Aggregates
COUNT()
,SUM()
,AVG()
같은 함수들로 그룹 내부의 값들을 계산한다.- 단독으로 쓰면 행 하나가 출력되지만, 보통은
GROUP BY
와 함께 많이 사용한다.
GROUP BY 시각화
sqlSELECT user_id FROM comments GROUP BY user_id;
이 쿼리를 실행하면:
comments
테이블 안의user_id
값들을 중복 없이(unique) 그룹으로 만든다.- 결과는 마치 user_id별로 댓글들을 따로 모은 그룹 테이블이 생긴 것처럼 볼 수 있다.
아래와 같이 표현해볼 수도 있다.
grouped comments
라는 테이블이 있다고 생각- 이 테이블은 맨 왼쪽에 GROUPED user_id라는 열이 있고, 이 열 안에는 원래 데이터의 원래 데이터들이 속하게 됨
- 테이블의 각 데이터를 해당되는 user_id에 할당해서 결과 반환
⇒ 이렇게 묶인 데이터를 좀 더 실용적으로 활용하려면 AGGREGATE랑 함께 쓰여야한다.
집계 함수(Aggregate Functions)
함수 | 설명 |
---|---|
COUNT() | 값의 개수를 센다 |
SUM() | 값들의 합을 구한다 |
AVG() | 평균을 구한다 |
MIN() | 최솟값을 구한다 |
MAX() | 최댓값을 구한다 |
예를 들면, 아래의 쿼리는 전체 comments
테이블에서 가장 큰 id
하나를 반환한다.
sqlSELECT MAX(id) FROM comments;
이렇게 AGGREGATE FUNCTION을 쓰면 일반 row는 함께 못 SELECT
한다.
GROUP BY와 집계 함수 함께 사용하기
예시 1. 유저별로 작성한 comments 수
sqlSELECT user_id, COUNT(id) FROM comments GROUP BY user_id;
user_id
를 기준으로 댓글들을 그룹으로 묶고, 각 유저가 쓴 댓글 수를 센다.
- 참고:
COUNT(id)
는id
가 NULL이면 무시한다.- 전체 row 수를 셀 때는
COUNT(*)
를 쓰는게 안전하다.
예시 2. 각 사진별 달린 comments 수
- 이 케이스는 여러 테이블을 JOIN할 필요 없이, comments 테이블만으로 가능
sqlSELECT photo_id, COUNT(*) FROM comments GROUP_BY photo_id;
HAVING으로 그룹 필터링하기
GROUP BY
로 그룹을 만든 후, 조건을 걸고 싶을 때는 WHERE
대신 HAVING
을 사용한다.
실행 순서는 아래와 같다.
FROM
- 기본 테이블 선택JOIN
- 다른 테이블들과 결합WHERE
- row 단위 필터링GROUP BY
- 특정 컬럼 기준으로 그룹화HAVING
- 그룹 단위로 조건 걸기
WHERE
은 행(Row)에 작동HAVING
은 그룹(group)에 작동
예시 : 특정 조건을 만족하는 그룹만 필털이
photo_id가 3보다 작고 photo가 2개 이상의 커멘트를 가진 사진들의 커멘트 수 구하기
sqlSELECT photo_id, COUNT(*) AS comment_count FROM comments WHERE photo_id < 3 GROUP BY photo_id HAVING COUNT(*) >= 2;
WHERE photo_id < 3
는 그룹 만들기 이전에 필터HAVING COUNT(*) >= 2
는 그룹 이후에 조건