GROUP BY 절은 테이블을 지정한 컬럼 기준으로 그룹화한 뒤, 그룹별 통계 정보를 계산할 때 사용합니다.
본 포스트에서는 GROUP BY의 기본 개념부터 다양한 실전 예제, HAVING 절 활용, 실행 순서까지 단계별로 정리했습니다.
1. GROUP BY 기본 개념
GROUP BY 절은 테이블의 여러 행(row)을 지정한 컬럼 기준으로 묶어(group),
각 그룹별로 집계함수(COUNT, SUM, AVG, MAX, MIN 등)를 적용할 수 있도록 합니다.
2. GROUP BY에 들어갈 수 있는 항목
- 컬럼명
- 상수
- 집계 함수(통계함수)
예를 들어, GROUP BY deptno, '2025년도', COUNT(*) 처럼
고정 문자열이나 집계함수 결과도 그룹핑 키로 사용할 수 있습니다.
3. 실습 예제
3-1. 부서별 인원수·급여 통계
SELECT
TO_CHAR(SYSDATE, 'YYYY') || '년도' AS 년도,
deptno AS 부서번호,
COUNT(*) AS 인원수,
SUM(sapay) AS 급여합계,
FLOOR(AVG(sapay)) AS 급여평균,
MAX(sapay) AS 최고급여액,
MIN(sapay) AS 최저급여액
FROM sawon
GROUP BY deptno
ORDER BY deptno;
설명
- TO_CHAR(SYSDATE,'YYYY')||'년도'로 조회 시점을 년도 레이블로 출력
- GROUP BY deptno로 부서별로 묶은 뒤, 집계함수로 통계값 계산
3-2. 부서별 성별 인원수
SELECT
TO_CHAR(SYSDATE, 'YYYY') || '년도' AS 년도,
deptno AS 부서번호,
sasex AS 성별,
COUNT(*) AS 인원수
FROM sawon
GROUP BY deptno, sasex
ORDER BY deptno, sasex;
3-3. 입사 연도별 인원수
SELECT
hire_year AS 입사년도,
COUNT(*) AS 인원수
FROM sawon_view2
GROUP BY hire_year
ORDER BY hire_year;
3-4. 입사 월별 인원수
SELECT
hire_month AS 입사월,
COUNT(*) AS 인원수
FROM sawon_view2
GROUP BY hire_month
ORDER BY hire_month;
3-5. 입사 계절별 인원수
SELECT
hire_season AS 입사계절,
COUNT(*) AS 인원수
FROM sawon_view2
GROUP BY hire_season
ORDER BY hire_season;
3-6. 입사 연대별 인원수
SELECT
(FLOOR(hire_year/10) || '0년대') AS 입사연대,
COUNT(*) AS 인원수
FROM sawon_view2
GROUP BY FLOOR(hire_year/10)
ORDER BY FLOOR(hire_year/10);
설명
- FLOOR(hire_year/10) 연산 결과를 그룹 키로 사용
- '0년대' 라벨을 붙여 가독성 향상
3-7. 고객뷰 성별 인원수
SELECT
gogender AS 성별,
COUNT(*) AS 인원수
FROM gogek_view2
GROUP BY gogender
ORDER BY gogender;
3-8. 고객뷰 지역(광역시)별 인원수
SELECT
SUBSTR(goaddr,1,2) AS 지역코드,
COUNT(*) AS 인원수
FROM gogek_view2
GROUP BY SUBSTR(goaddr,1,2)
ORDER BY SUBSTR(goaddr,1,2);
3-9. 고객뷰 연령대별 인원수
SELECT
(FLOOR(goage/10) || '0대') AS 연령대,
COUNT(*) AS 인원수
FROM gogek_view3
GROUP BY FLOOR(goage/10)
ORDER BY FLOOR(goage/10);
3-10. 사원뷰 성씨별 인원수
SELECT
SUBSTR(saname,1,1) AS 성씨,
COUNT(*) AS 인원수
FROM sawon_view2
GROUP BY SUBSTR(saname,1,1)
ORDER BY SUBSTR(saname,1,1);
4. HAVING 절로 그룹 필터링
- WHERE 절은 그룹화 이전(개별 행)에 조건을 걸지만,
- HAVING 절은 그룹화 이후(집계 결과)에 조건을 걸 수 있습니다.
SELECT
deptno,
COUNT(*) AS 직원수
FROM sawon_view2
WHERE deptno != 100 -- ① 그룹화 전 필터
GROUP BY deptno -- ③ 그룹화
HAVING COUNT(*) >= 5 -- ④ 그룹화 후 필터
ORDER BY deptno; -- ⑥ 정렬
5. 실행 순서 이해하기
select
deptno,count(*) -- ⑤
from sawon_view2 -- ①
where deptno !=100 -- ②
group by deptno -- ③
having count(*)>=5 -- ④
order by deptno -- ⑥
6. 팁 & 주의사항
- NULL 값은 COUNT(col)에서 제외됩니다. 전체 행수는 COUNT(*) 사용
- 평균(AVG) 소수점 자릿수 조정: ROUND(AVG(col), 2)
- 대규모 데이터셋: 인덱스·파티셔닝을 통한 집계 성능 최적화
- 너무 복잡한 그룹화 로직은 뷰(View)로 분리해 재사용성 확보
'Oracle' 카테고리의 다른 글
| Oracle JOIN(조인) 총정리 (2) | 2025.08.14 |
|---|---|
| Oracle 뷰(View) 이해 및 활용 가이드 (4) | 2025.08.13 |
| Oracle 집계 함수(aggregate functions) 정리 및 실습 (0) | 2025.08.13 |
| Oracle SQL 서브쿼리(Subquery)와 집합 연산자 (4) | 2025.08.13 |
| Oracle DECODE, CASE, NVL/NVL2, VIEW 함수 정리 및 예제 (4) | 2025.08.08 |