
Groupby 는 테이블에서 같은 값을 묶는 기능입니다.
하나의 테이블에서는 의미를 이해하기 쉽지만 여러 테이블에서라면 난이도가 상승하게 됩니다.
| 사원ID | 이름 | 부서ID (속성1) | 직급 (속성2) | 급여 |
| 1 | 김철수 | 개발팀 | 대리 | 4,000 |
| 2 | 이영희 | 개발팀 | 대리 | 4,500 |
| 3 | 박민수 | 개발팀 | 과장 | 5,500 |
| 4 | 최성민 | 인사팀 | 대리 | 3,800 |
| 5 | 정수연 | 인사팀 | 과장 | 5,000 |
| 6 | 홍길동 | 인사팀 | 과장 | 5,200 |
테이블 하나인 경우에, 이해하기 쉽습니다.
문제: 사원 테이블에서 부서별로, 직급별로 인원수를 구해보셔라~
접근해야 할 방식은
1. 부서별로 개발팀 3개 행, 인사팀 3개 총 2개의 그룹으로 나눈다.
2. 그 그룹 안에서 직급을 기준으로 그룹을 나눈다.
전체 테이블
│
├── 개발팀
│ ├── 대리
│ │ ├ 김철수
│ │ └ 이영희
│ │
│ └── 과장
│ └ 박민수
│
└── 인사팀
├── 대리
│ └ 최성민
│
└── 과장
├ 정수연
└ 홍길동
이렇게 그룹화 하면 되구,
Select 부서ID, 직급, COUNT(*) AS 인원수
From 사원
Group By 부서ID, 직급;
위에처럼 SQL로 쓴다면
| 부서ID | 직급 | 인원수 |
| 개발팀 | 대리 | 2 |
| 개발팀 | 과장 | 1 |
| 인사팀 | 대리 | 1 |
| 인사팀 | 과장 | 2 |
이렇게 결과가 나옵니다.
여기에 문제에서 인원수 2명 이상만으로 요구사항이 붙는다면 HAVING을 사용하면 됩니다.
SELECT 부서ID,
직급,
COUNT(*) AS 인원수
FROM 사원
GROUP BY 부서ID, 직급
HAVING COUNT(*) >= 2;
그런데 테이블이 여러개가 된다면 group by를 활용하여 쿼리 구성 난이도가 높아지게 됩니다.

문제 : 도서별로 처음 대출된 도서의 도서명, 출판사, 대출시작일자를 조회하세요.
접근 방법 1: "어차피 테이블이 3개여도 where로 PK, FK를 연결지어서, 한 테이블로 합쳐지고, 그거 기반으로 Group By 도서명해서, 대출일자 앞에 MIN(대출시작일자) 붙이면 끝나는거 아닌가?"
이 생각을 SQL로 옮기면
Select B.도서명, C.출판사명, Min(A.대출시작일자) AS 최소대출일, A.대출종료일자
From 대출 A, 도서 B, 출판사 C
Where A.도서ID = B.도서ID AND A.출판사ID = C.출판사ID
Gruop By B.도서명
이렇게 나오게 되는데.. 이러면 디비 시스템이 알아서 가장 처음에 대출된 날짜를 찾고, 그 날짜에 맞는 출판사, 종료일도 예쁘게 매칭해주겠지?
ORA-00979: not a GROUP BY expression
하지만 컴퓨터는 이런 에러를 던지며 실행을 못하겠다고 합니다.
천천히 과정을 살펴보겄습니다.
1. Where절로 다 묶었을 때 데이터 모습
| B.도서명 | C.출판사명 | A.대출시작일자 (타임라인) | A.대출종료일자 |
| 개미 | 민음사 | 2026-01-01 | 2026-01-10 |
| 개미 | 맙소사 | 2026-03-15 | 2026-03-25 |
| 개미 | 민음사 | 2026-05-20 | 2026-05-30 |
| 베짱이 | 황금가지 | 2026-02-10 | 2026-02-20 |
| 베짱이 | 황금가지 | 2026-04-01 | 2026-04-10 |
| 두루미 | 창비 | 2026-01-15 | 2026-01-25 |
| 두루미 | 창비 | 2026-06-01 | 2026-06-10 |
개미 라는 책 한권에 정직하게 이렇게 1월, 3월, 5월 대출 기록이 펼쳐져 있습니다.
배짱이와 두루미도 마찬가지죠.
2. 여기서 Group By를 하게된다면
Groupby B.도서명
이 쿼리를 읽는 순간, 컴퓨터는 "도서명이 똑같은 애들은 무조건 한줄로 앞축해야 해"
그 이유는 "도서명을 기준으로" 개미, 베짱이, 두루미 그룹을 만들게 됩니다.
| 개미 | 민음사 | 2026-01-01 | 2026-01-10 |
| 개미 | 맙소사 | 2026-03-15 | 2026-03-25 |
| 개미 | 민음사 | 2026-05-20 | 2026-05-30 |
| 베짱이 | 황금가지 | 2026-02-10 | 2026-02-20 |
| 베짱이 | 황금가지 | 2026-04-01 | 2026-04-10 |
| 두루미 | 창비 | 2026-01-15 | 2026-01-25 |
| 두루미 | 창비 | 2026-06-01 | 2026-06-10 |
3개 그룹이 만들어지는거 OK 그리고 각각의 그룹에서 최소 대출 시작일자
개미 -> 2026-01-01
베짱이 -> 2026-02-10
두루미 -> 2026-01-15
이렇게 선정 됬습니다.
그러나 문제는 여기서 발생하게 되는데, 대출 종료 일자의 데이터가 각 그룹별로 보니까... 개미의 경우 3개가 있습니다. 이것들 중 하나를 선택해야하는데....
개미의 경우 종료 일자 3개중 뭐쓰지?
베짱이, 두루미의 경우 종료일자 각각 2개중 뭐를 써야할지 모릅니다.
출판사명 또한 마찬가지입니다. 위의 경우 개미의 경우에가 문제가 발생하고, 혹여나 같은 도서명이지만 출판사명이 다른 데이터가 들어온다면 마찬가지로 같은 에러를 발생하게 됩니다.
여기서 키 포인트는 Group By에 사용된 속성명만, 그 Select에 사용할 수있고, 그 이외의 경우에 Select에서 속성을 추가할 경우에는 집계함수만 가능하다!
이것이 바로 GROUP BY 절에 적지 않은 일반 속성명을 SELECT 절에 그냥 적었을 때 발생하는 '결정 장애 에러(not a GROUP BY expression)' 입니다.
그럼 만약에
SELECT
B.도서명,
MAX(C.출판사명) AS 출판사명,
MIN(A.대출시작일자) AS 최소대출일,
MAX(A.대출종료일자) AS 대출종료일자
FROM 대출 A, 도서 B, 출판사 C
WHERE A.도서ID = B.도서ID AND A.출판사ID = C.출판사ID
GROUP BY B.도서명;
이렇게 쿼리를 짠다면, 에러가 발생될까요?
에러는 발생하지 않겠지만, 문제에서의 요구사항에 벗어나는 결과를 도출하게 됩니다...
문제 : 도서별로 처음 대출된 도서의 도서명, 출판사, 대출시작일자를 조회하세요.
정답에 가까운 쿼리는 다음과 같습니다.
1. "도서별로 처음 대출된 도서"는 쉽게 Group By로 구할 수 있습니다.
Select Min(대출시작일자) AS 최소대출일
From 대출
Group By 도서ID
이렇게 될 경우 쿼리 결과는
| 도서ID (Group By에서 사용된 속성 OK) | 최소대출일 (집계 완료함수 OK) |
| 개미 | 2026-01-01 |
| 베짱이 | 2026-02-10 |
| 두루미 | 2026-01-15 |
이렇게 출력됩니다.
근데 정답이 아닌 이유는, 우리는 도서명, 출판사를 알아야 합니다.
그렇다면 다시 join으로 필터링 하는 where 키워드를 활용해서 사용하면 된답니다.
아까처럼 테이블들을 전부 연결시킨 후에, 우리가 원하는 "위에서 구했던, 최소대출일 데이터들이 담긴 테이블 D"의 속성명들과 비교해주면 됩니다.
Select B.도서명, C.출판사명, A.대출시작일자 AS 최소대출일
From 대출 A, 도서 B, 출판사 C, (Select 도서ID, Min(대출시작일자) AS 대출시작일자
From 대출
Group By 도서ID) D
// 1. 원하는 최소대출시작일자 데이터만 가져오기
Where A.도서ID = D.도서ID AND A.대출시작일자 = D.대출시작일자
//2. 원본 대출 테이블 중에 최소 대출 시작일자들의 도서ID 가진 행들 골라내기
And A.도서ID = B.도서ID
And A.출판사ID = C.출판사ID
// 3. 그 최소 대출 시작일자의 특정 대출 행들을 가지구 도서명, 출판사명과 맵핑해서 큰 테이블 만들기
4. 큰 테이블 중 Select에서 이제 요구사항에서 원하는 속성들로 결과를 추출하기~..
'스마 (SQL Master) 도전! > Deep Dive !!' 카테고리의 다른 글
| [DB 딥다이브] 인조 식별자만 믿었다간 서비스 터진다..? 조인 성능과 복합 인덱스 물리 메커니즘 파해치기 (3) | 2026.06.10 |
|---|---|
| [SQL] GROUP BY 오류: "group by 표현식이 아닌것들.. 원인과 해결 방법 (0) | 2026.03.05 |