sungyup's.

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 시각화

sql
SELECT user_id FROM comments GROUP BY user_id;

이 쿼리를 실행하면:

  • comments 테이블 안의 user_id 값들을 중복 없이(unique) 그룹으로 만든다.
  • 결과는 마치 user_id별로 댓글들을 따로 모은 그룹 테이블이 생긴 것처럼 볼 수 있다.

아래와 같이 표현해볼 수도 있다.

  1. grouped comments라는 테이블이 있다고 생각
  2. 이 테이블은 맨 왼쪽에 GROUPED user_id라는 열이 있고, 이 열 안에는 원래 데이터의 원래 데이터들이 속하게 됨
  3. 테이블의 각 데이터를 해당되는 user_id에 할당해서 결과 반환

⇒ 이렇게 묶인 데이터를 좀 더 실용적으로 활용하려면 AGGREGATE랑 함께 쓰여야한다.

집계 함수(Aggregate Functions)

함수설명
COUNT()값의 개수를 센다
SUM()값들의 합을 구한다
AVG()평균을 구한다
MIN()최솟값을 구한다
MAX()최댓값을 구한다

예를 들면, 아래의 쿼리는 전체 comments 테이블에서 가장 큰 id 하나를 반환한다.

sql
SELECT MAX(id) FROM comments;

이렇게 AGGREGATE FUNCTION을 쓰면 일반 row는 함께 못 SELECT한다.

GROUP BY와 집계 함수 함께 사용하기

예시 1. 유저별로 작성한 comments 수

sql
SELECT user_id, COUNT(id) FROM comments GROUP BY user_id;
  • user_id를 기준으로 댓글들을 그룹으로 묶고, 각 유저가 쓴 댓글 수를 센다.
  • 참고:
  • COUNT(id)id가 NULL이면 무시한다.
  • 전체 row 수를 셀 때는 COUNT(*)를 쓰는게 안전하다.

예시 2. 각 사진별 달린 comments 수

  • 이 케이스는 여러 테이블을 JOIN할 필요 없이, comments 테이블만으로 가능
sql
SELECT photo_id, COUNT(*) FROM comments GROUP_BY photo_id;

HAVING으로 그룹 필터링하기

GROUP BY로 그룹을 만든 후, 조건을 걸고 싶을 때는 WHERE 대신 HAVING을 사용한다.

실행 순서는 아래와 같다.

  1. FROM- 기본 테이블 선택
  2. JOIN- 다른 테이블들과 결합
  3. WHERE- row 단위 필터링
  4. GROUP BY- 특정 컬럼 기준으로 그룹화
  5. HAVING- 그룹 단위로 조건 걸기

WHERE은 행(Row)에 작동 HAVING은 그룹(group)에 작동

예시 : 특정 조건을 만족하는 그룹만 필털이

photo_id가 3보다 작고 photo가 2개 이상의 커멘트를 가진 사진들의 커멘트 수 구하기

sql
SELECT 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그룹 이후에 조건