지난 글에서 다룬 집계 함수(Aggregations)에서 더 나아가보자. 이번 글에서는 그룹 함수와 HAVING문을 이용해보자.
■ GROUP BY
Group by로 그룹화한다는 건 무슨 뜻일까? 어떤 열을 지정하여 그룹화한다는 말은 지정된 열의 값이 같은 행으로 표현된다는 뜻이다.
얼핏보면 중복을 제거하는 DISTINCT와 비슷해보인다. GROUP BY와 DISTINCT의 차이는 집계 함수와의 사용 여부이다. GROUP BY를 사용하면, 집계함수의 인수로 그룹이 넘겨진다. 개념으로만 들어서는 좀 헷갈리는데 예시를 통해 살펴보자.
Name | Score | Place |
AAA | 50 | 1 |
BBB | 100 | 1 |
CCC | 80 | 2 |
위의 데이터를 Place별로 묶어서 그룹화를 하고 각 그룹의 평균 점수를 알고 싶다. 쿼리문은 다음과 같다.
SELECT Place, AVG(SCORE) AS AVG_SCORE FROM Scores GROUP BY Place;
결과는 아래와 같이 나올 것이다.
Place | AVG_SCORE |
---|---|
1 | 50 |
2 | 80 |
한 가지 더 주의할 점은 GROUP BY에 지정한 열 이외의 열을 SELECT할 때는 반드시 집계함수를 사용해야한다. 즉, 위의 쿼리문처럼 GROUP BY로 Place를 했다면, SELECT에 Place는 집계함수 없이 사용이 가능하지만 Score는 반드시 집계함수와 함께 사용해야 한다.
■ WHERE vs. HAVING
이번에는 조건부를 지정할 때 사용하는 WHERE와 HAVING의 차이점에 대해 살펴보자.
WHERE의 경우 그룹이 되기 전에 데이터를 필터링한다. 반대로, HAVING의 경우 그룹화 후의 데이터를 필터링한다. WHERE에 의해 제거된 행은 그룹에 포함되지 않는다.
예를 들어 HAVING은 다음과 같은 경우에 사용할 수 있다.
SELECT Product, SUM(Sales) FROM Products GROUP BY Product HAVING SUM(Sales) >= 100;
쿼리문을 해석하자면, Products 테이블에서 제품별 총 매출액이 100 이상인 제품만 필터링한다. 집계함수는 WHERE 문의 조건식에서 사용할 수 없다는 것도 상기하면 좋을 것 같다. 이는 SQL이 처리하는 순서때문인데, WHERE문으로 행을 검색하는 처리가 GROUP BY로 그룹화하는 처리보다 먼저 실행되기 때문이다. 내부적인 처리 순서는 WHERE > GROUP BY > HAVING > SELECT > ORDER BY 이다.
참고로, GROUP BY와 여러 구문의 작성 순서는 다음과 같다. ORDER BY는 거의 대부분 마지막에 위치함을 기억하자.
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
또한, 그룹화할 열에 NULL값이 있는 경우, NULL도 그룹화된다는 것을 유념하자. 즉, NULL이 여러개 있을 경우 하나의 NULL로 그룹화된다.