GROUP BY는 SELECT 절에서 데이터를 그룹화 하는 명령어이다. GROUP BY는 집계함수와 함께 사용할 수 있다.
PostgreSQL의 집계함수
집계함수 : 여러 개의 row를 입력 값으로 받고 하나의 출력을 함
집계함수 종류
- COUNT : 결과 값들의 개수 반환(중복 값도 모두 counting)
- SUM : 결과 값들의 합 반환
- AVG : 결과 값들의 평균 값 반환
- MAX : 결과 값들 중 최대값 반환
- MIN : 결과 값들 중 최소값 반환
[ GROUP BY의 계산 순서 ]
- FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
- GRUOP BY가 SELECT보다 먼저 수행되므로 SELECT절에서 사용된 alias는 사용할 수 없다.
-- 집계함수 없이 그룹화
SELECT
customer_id
FROM
payment
GROUP BY
customer_id ;
⇒ 실행 결과를 보면, 집계함수를 적용하지 않았기 때문에 DISTINCT와 동일하게 동작한다.
-- 집계함수 SUM을 사용
SELECT
customer_id,
SUM (amount)
FROM
payment
GROUP BY
customer_id;
-- 두 개 컬럼을 그룹화하기
SELECT
customer_id,
SUM (amount),
rental_id
FROM
payment
GROUP BY
customer_id,
rental_id
ORDER BY
customer_id,
rental_id;
두 개를 기준으로 그룹화 할 경우 (cusomer_id, rental_id 1), (cusomer_id, rental_id 2), (cusomer_id, rental_id 3) ... 을 인덱스로 그룹화한다.
rental_id를 GROUP BY 절에 넣지 않으면 다음과 같은 에러 발생한다.(아래 설명 참고)
ERROR: 오류: column "payment.rental_id" 는 반드시 GROUP BY 절 내에 있어야 하던지 또는 집계 함수 내에서 사용되어져야 한다
LINE 4: rental_id
-- JOIN과 함께 그룹화
SELECT
c.first_name || ' ' || c.last_name AS f_name,
SUM (p.amount) AS amount
FROM
payment AS p
INNER JOIN customer AS c
ON p.customer_id = c.customer_id
GROUP BY
f_name
ORDER BY
amount DESC;
[ 질문 ]
쿼리 순서는 GROUP BY가 SELECT보다 먼저인데, 컬럼 alias를 GROUP BY 절에서 사용할 수 있는 이유는 무엇일까?
→ 원래 쿼리 순서 상 GROUP BY가 SELECT보다 먼저 수행되므로 SELECT에서 사용된 alias를 사용할 수 없는 것이 원칙이지만, DBMS가 처리를 해줘서 사용 가능 한 것이다!
지금 까지 사용한 테이블 payment에는 payment_date라는 컬럼이 있는데 이 컬럼은 타임스템프 컬럼이다. 따라서 그냥 사용할 경우 다음과 같은 결과가 나온다.
(타임스탬프는 날짜와 시간을 함께 제공하는 데이터 형태)
-- 타임스템프 컬럼 다루기
SELECT
payment_date paid_date,
SUM(amount) sum
FROM
payment
GROUP BY
payment_date;
따라서 날짜 정보만 보기 위해서는 DATE 함수를 사용한다.
-- 타임스탬프에서 DATE 함수 사용하기
SELECT
DATE(payment_date) paid_date,
SUM(amount) sum
FROM
payment
GROUP BY
DATE(payment_date);
HAVING은 GROUP BY와 함께 사용 되며 그룹의 조건을 제시하여 조건에 맞는 그룹만 필터링 할 때 사용한다.
[ HAVING의 계산 순서 ]
FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
[ HAVING vs WHERE ]
- HAVING : 조건을 그룹에 적용
- WHERE : 조건을 조회하는 행에 적용
-- 집계함수 SUM과 함께 사용하기
SELECT
customer_id,
SUM (amount)
FROM
payment
GROUP BY
customer_id
HAVING
SUM (amount) > 200;
customer_id를 기준으로 그룹화 하여 customer_id 별 결제 금액 총합 조회하고, 총합이 $200이 넘는 그룹만 조회
-- 집계함수 COUNT와 함께 사용하기
SELECT
store_id,
COUNT (customer_id)
FROM
customer
GROUP BY
store_id
HAVING
COUNT (customer_id) > 300;
store_id를 기준으로 그룹화 후 데이터 조회한 후, 고객 수가 300이 넘는 그룹만 조회