그룹 함수·조인·하위 질의
쉽게 말하면
여러 행을 묶어 합계·평균·개수를 구할 땐 GROUP BY로 묶고 집계 함수를 써요. 묶은 그룹 중 조건에 맞는 것만 남길 땐 WHERE가 아니라 HAVING을 써요. 두 표를 공통 열로 이어 붙이는 게 조인이고, 짝이 없는 행까지 보여 주려면 외부 조인을 써요. 하위 질의는 SELECT 안에 넣은 또 다른 SELECT예요. 집계 함수는 NULL을 빼고 계산한다는 점도 꼭 기억해요.
시험용 정의
집계 함수는 여러 행을 하나의 값으로 계산한다: COUNT, SUM, AVG, MAX, MIN. COUNT(*)는 모든 행을 세지만 COUNT(열)과 다른 집계 함수는 NULL을 제외한다. GROUP BY는 같은 값끼리 묶고, HAVING은 묶은 그룹에 조건을 건다. 조인은 두 테이블을 결합하는 것으로 내부 조인(INNER JOIN, 양쪽에 일치하는 행만)과 외부 조인(LEFT·RIGHT·FULL OUTER JOIN, 짝이 없는 행도 NULL로 채워 포함), 자연 조인, 교차 조인, 셀프 조인이 있다. 하위 질의(서브쿼리)는 SQL 안에 넣은 SELECT로 IN, EXISTS, 비교 연산자와 함께 쓴다. 집합 연산은 UNION(중복 제거 합), UNION ALL(중복 포함), INTERSECT(교집합), EXCEPT/MINUS(차집합)다.
비유로 이해하기
반 대항 체육대회다. GROUP BY는 반별로 줄 세우기, SUM은 반별 점수 합, HAVING은 '합계 100점 넘는 반만 시상'이다. 조인은 학생 명단과 출전 기록을 학번으로 맞대는 것, 외부 조인은 출전 기록이 없는 학생도 명단에 빈칸으로 남기는 것이다.
자세히
먼저 알아 둘 말
| 말 | 뜻 |
|---|---|
| 집계 함수 | 여러 행으로 값 하나를 만드는 함수 (그룹 함수) |
| 내부 조인 | 조인 조건에 맞는 행만 결합 |
| 외부 조인 | 한쪽에 짝이 없어도 그 행을 남기고 상대 열은 NULL |
| 하위 질의 | 다른 SQL 문 안에 들어간 SELECT |
| 상관 하위 질의 | 바깥 질의의 열을 참조해 행마다 다시 실행되는 하위 질의 |
WHERE vs HAVING
| 구분 | WHERE | HAVING |
|---|---|---|
| 거르는 대상 | 개별 행 (묶기 전) | 그룹 (묶은 뒤) |
| 집계 함수 | 쓸 수 없다 | 쓸 수 있다 |
| 예 | WHERE year >= 2 | HAVING COUNT(*) >= 2 |
조인 종류
| 조인 | 모양 | 결과 |
|---|---|---|
| 내부 | FROM student s JOIN enroll e ON s.sno = e.sno | 수강 기록이 있는 학생만 |
| 왼쪽 외부 | FROM student s LEFT OUTER JOIN enroll e ON s.sno = e.sno | 모든 학생, 수강 없으면 NULL |
| 자연 | FROM student NATURAL JOIN enroll | 같은 이름 열(SNO)로 자동 조인, 열 하나만 남김 |
| 교차 | FROM student CROSS JOIN course | 모든 조합 (6 × 3 = 18행) |
| 셀프 | 같은 테이블을 별칭 두 개로 | 사원-관리자처럼 자기 참조 |
하위 질의와 집합 연산
WHERE sno IN (SELECT sno FROM enroll WHERE cno = 'C101'): C101 수강생WHERE EXISTS (SELECT 1 FROM enroll e WHERE e.sno = s.sno): 수강 기록이 하나라도 있으면 참WHERE score > (SELECT AVG(score) FROM student): 평균보다 높은 학생- UNION은 중복 제거, UNION ALL은 중복 포함. 두 SELECT의 열 수와 타입이 맞아야 한다
시험에 이렇게 나와요
- 집계 함수 → COUNT·SUM·AVG·MAX·MIN (CREATE는 아님)
- HAVING → GROUP BY로 묶은 그룹에 조건을 건다
- 두 테이블 조인 → FROM에 두 테이블, WHERE에 연결 조건과 검색 조건
확인 문제
Q1. 학과별 평균 점수가 80 이상인 학과만 보이려면 조건을 어디에 써야 할까요?
- GROUP BY AVG(score) >= 80
- ORDER BY AVG(score) >= 80
- WHERE AVG(score) >= 80
- HAVING AVG(score) >= 80
정답 보기
4번 HAVING AVG(score) >= 80
WHERE는 묶기 전 행을 거르고, HAVING은 GROUP BY로 묶은 뒤 그룹을 거른다. 집계 함수 조건은 HAVING에 쓴다.
Q2. 점수가 (88, 72, NULL, 80)인 4개 행에서 AVG(score)의 결과는?
- 오류
- 80
- 60
- NULL
정답 보기
2번 80
NULL을 빼고 (88 + 72 + 80) / 3 = 80.
Q3. 두 SELECT 결과를 합치되 중복 행도 그대로 두는 연산은?
- UNION
- EXCEPT
- INTERSECT
- UNION ALL
정답 보기
4번 UNION ALL
UNION ALL이다. UNION은 중복을 없애고, INTERSECT는 교집합, EXCEPT는 차집합이다.
Q4. 왼쪽 테이블의 모든 행을 남기고 오른쪽에 짝이 없으면 NULL로 채우는 조인은?
- NATURAL JOIN
- LEFT OUTER JOIN
- INNER JOIN
- CROSS JOIN
정답 보기
2번 LEFT OUTER JOIN
LEFT OUTER JOIN이다. INNER JOIN은 양쪽에 짝이 있는 행만, CROSS JOIN은 모든 조합을 만든다.
Q5. 다음 중 문법적으로 잘못된 것은?
- SELECT dept, COUNT(*) FROM student WHERE COUNT(*) > 1 GROUP BY dept
- SELECT MAX(score) FROM student
- SELECT dept FROM student GROUP BY dept HAVING COUNT(*) > 1
- SELECT dept, COUNT(*) FROM student GROUP BY dept
정답 보기
1번 SELECT dept, COUNT(*) FROM student WHERE COUNT(*) > 1 GROUP BY dept
WHERE에는 집계 함수를 쓸 수 없다. HAVING을 써야 한다.
헷갈리기 쉬운 O·X
COUNT(열)은 그 열이 NULL인 행도 센다.
정답 보기
X COUNT(열)은 NULL을 제외. 모든 행은 COUNT(*).
HAVING 절에는 집계 함수를 쓸 수 있다.
정답 보기
O
내부 조인은 조인 조건에 맞지 않는 행도 NULL로 채워 보여 준다.
정답 보기
X 그건 외부 조인.