GROUP BY
앞서 살펴본 집계 함수들은 하나의 그룹으로 묶어서 계산하는데, 그 그룹을 하나가 아닌 여러 개로 분리하기 위해서 사용한다.
뒤에 지정한 열에 대하여 같은 값들을 묶어 하나의 그룹으로 만든다.
여러 열을 지정하여 지정된 모든 열의 값이 같은 행만 그룹으로 묶는 것도 가능하다.
뒤에 오는 열은 테이블에서 바로 가져오는 열 이거나, select 절에서 수식을 사용한다면 같은 수식을 사용해야한다.
별칭은 사용할 수 없다. (내가 사용중인 PostgreSQL 에서는 현재 사용 가능하다.)
문자나 메모와 같은 가변 길이의 데이터형에는 사용할 수 없다.
그룹 함수를 제외한 SELECT 절에 있는 모든 열은 GROUP BY 절에 존재해야 한다.
그룹핑하는 열에 NULL 값이 있다면 NULL 값으로 그룹을 만든다.
WHERE 절 뒤에, ORDER BY 절 앞에 온다.
그룹 필터링
앞서 사용했던 WHERE 절은 행에 대한 필터링을 한다.
그룹에 속한 행의 개수가 2개 이상인 그룹만 가져오는 등의 연산 즉, 그룹 필터링을 위해 HAVING 절이 존재한다.
SELECT 문 순서
SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY
도전 과제
OrderItems 테이블에서 주문 번호에 해당하는 줄 수(order_lines) 를 정렬하여 출력하라.
SELECT count(1) AS order_lines FROM OrderItems GROUP BY order_num ORDER BY order_lines;
Products 테이블에 있는 prod_price를 사용하여, 각 판매처에서 취급하는 가장 저렴한 항목을 cheapest_item 이라 하고, 가격순으로 정렬하여 출력하라.
SELECT min(prod_price) AS cheapest_item FROM Products GROUP BY vend_id ORDER BY 1;
100개 이상의 항목을 주문한 주문 번호를 가져오는 SQL 문을 작성하라.
SELECT order_num FROM OrderItems GROUP BY order_num HAVING sum(quantity) >= 100;
주문액의 합이 1000 이상인 모든 주문 번호를 가져와 주문 번호로 정렬하는 SQL 문을 작성하라.
SELECT order_num FROM OrderItems GROUP BY order_num HAVING sum(quantity * item_price) >= 1000 ORDER BY order_num;
다음 SQL 문은 무엇이 잘못되었는가? - GROUP BY 절에 COUNT(*) 을 사용함
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY items
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
참고.
일부 SQL 실행 환경에서는 ORDER BY 절과 같이 열의 위치를 통해 GROU BY 1, 2 와 같이 사용할 수 있다.
대다수 DBMS 에서는 GROUP BY가 명시되지 않으면 WHERE절과 HAVING절을 똑같이 처리한다.
주의.
GROUP BY 절을 사용하면 해당 열의 값으로 정렬해서 반환하는 DBMS 도 있는데, 이는 SQL 실행 환경마다 다르고, 확신할 수 없으므로 ORDER BY 절을 통해 명시해주는 것이 좋다.