SQL은 SELECT부터 쓰지만, 처리는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순서로 합니다.
처리 순서를 알면 어느 절에서 무엇을 쓸 수 있는지 설명할 수 있습니다. 예를 들어 SELECT에서 붙인 별칭(alias)은 ORDER BY에서는 쓸 수 있지만 WHERE에서는 쓸 수 없습니다. 합계 같은 집계 결과로 거르는 조건은 WHERE가 아니라 HAVING에 써야 합니다. 두 규칙 모두 처리 순서에서 나옵니다. 그림의 쿼리는 SAL이 400 이상인 사원만 부서별로 합쳐, 합계가 500 이상인 부서를 합계가 큰 순서로 보여 줍니다.
1FROM에서 ORDER BY까지
쓰는 순서는 SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY입니다. Oracle은 HAVING을 GROUP BY 앞에 써도 받지만, 처리 순서는 바뀌지 않습니다.
| 순서 | 절 | 하는 일 | 그림의 쿼리에서 |
|---|---|---|---|
| 1 | FROM | 테이블을 가져옴 | EMP 6행 |
| 2 | WHERE | 행을 거름 | 4행 남음 |
| 3 | GROUP BY | 행을 묶음 | 그룹 3개 |
| 4 | HAVING | 그룹을 거름 | 그룹 2개 남음 |
| 5 | SELECT | 그룹마다 한 줄 | 2줄 |
| 6 | ORDER BY | 줄을 세움 | 880, 520 순 |
WHERE는 행을 하나씩 보는 단계라 아직 그룹이 없습니다.
그래서 SUM(SAL) 같은 집계 함수는 WHERE에 쓸 수 없고, 묶은 다음인 HAVING에 씁니다.
SAL이 300인 정하늘이 WHERE에서 빠지므로, DEPTNO가 NULL인 그룹도 생기지 않습니다.
2별칭을 쓸 수 있는 곳
별칭은 다섯째인 SELECT를 처리할 때 붙습니다.
앞서 처리되는 WHERE·GROUP BY·HAVING은 그 이름을 모르므로 식을 다시 써야 합니다.
그림의 HAVING이 TOTAL 대신 SUM(SAL)을 쓴 까닭입니다.
| 절 | 처리 순서 | 별칭(시험 기준) |
|---|---|---|
| WHERE | 2 | 못 씀 |
| GROUP BY | 3 | 못 씀 |
| HAVING | 4 | 못 씀 |
| ORDER BY | 6 | 씀 |
Oracle 23부터는 GROUP BY·HAVING에서도 별칭을 받지만, 시험 답은 표대로 고릅니다.
GROUP BY가 없으면 ORDER BY는 SELECT에 없는 열로도 정렬할 수 있습니다. GROUP BY가 있으면 줄이 이미 그룹마다 하나라, 그룹 안에 값이 여럿인 열로는 세울 수 없습니다. 그래서 ORDER BY에도 GROUP BY에 쓴 식, 집계 함수, 그 별칭만 올 수 있습니다. 어기면 Oracle은 ORA-00979 오류를 냅니다.
3결과 순서는 ORDER BY만 정한다
이 순서는 결과를 정하는 논리적인 순서입니다. 시험에서 말하는 'SELECT 문의 실행 순서'가 이것입니다. 실제로 데이터를 읽고 계산하는 차례는 DBMS가 정하며, 결과가 같다면 이와 다를 수 있습니다. 그래서 GROUP BY를 지난 그룹이 DEPTNO 순서로 서 있어도 그 순서는 보장되지 않습니다. 같은 쿼리도 DBMS나 실행 계획(execution plan, DBMS가 고른 처리 방법)에 따라 다른 순서로 나올 수 있으니, 순서가 필요하면 ORDER BY를 씁니다.
예제
그림의 쿼리입니다.
SELECT DEPTNO,
SUM(SAL) AS TOTAL
FROM EMP
WHERE SAL >= 400
GROUP BY DEPTNO
HAVING SUM(SAL) >= 500
ORDER BY TOTAL DESC;
| DEPTNO | TOTAL |
|---|---|
| 20 | 880 |
| 10 | 520 |
같은 조건을 WHERE에 쓰면 오류가 납니다.
SELECT DEPTNO,
SUM(SAL) AS TOTAL
FROM EMP
WHERE SUM(SAL) >= 500
GROUP BY DEPTNO;
Oracle은 ORA-00934(group function is not allowed here) 오류를 냅니다.
시험 포인트
- 쓰는 순서는 SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY입니다. Oracle은 HAVING을 GROUP BY 앞에 써도 받습니다.
- 처리 순서는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY입니다.
- WHERE는 행을 거르고, HAVING은 그룹을 거릅니다. 집계 함수가 들어간 조건은 HAVING에 씁니다.
- SELECT에서 붙인 별칭은 ORDER BY에서만 쓸 수 있고, WHERE·GROUP BY·HAVING에서는 쓸 수 없습니다. 시험은 이 규칙으로 답을 고릅니다.
- GROUP BY가 없으면 SELECT에 없는 열로도 정렬할 수 있습니다. GROUP BY가 있으면 ORDER BY에는 GROUP BY에 쓴 식, 집계 함수, 그 별칭만 옵니다.
- ORDER BY가 없으면 결과 행의 순서는 보장되지 않습니다.
확인 문제
1. 그림의 쿼리에서 WHERE SAL >= 400을 WHERE SAL >= 450으로 바꾸면 결과는 어떻게 될까요?
정답
10번 부서 한 줄만 남습니다.
| DEPTNO | TOTAL |
|---|---|
| 10 | 520 |
- WHERE를 거치면 김민준(520, 10번), 최유나(450, 30번), 강도윤(470, 20번) 3행이 남습니다.
- GROUP BY로 묶은 합계는 10번 520, 20번 470, 30번 450입니다.
- HAVING에서 합계가 500 이상인 그룹은 10번뿐입니다.
2. 다음 쿼리를 처리 순서대로 따라가면, WHERE 뒤에 몇 행, GROUP BY 뒤에 몇 그룹이 남고 결과는 무엇일까요?
SELECT DEPTNO,
MAX(SAL) AS TOP_SAL
FROM EMP
WHERE MGR IS NOT NULL
GROUP BY DEPTNO
HAVING MAX(SAL) >= 400
ORDER BY TOP_SAL;
정답
5행과 그룹 3개가 남고, 결과는 2줄입니다.
| DEPTNO | TOP_SAL |
|---|---|
| 30 | 450 |
| 20 | 470 |
- WHERE에서 관리자가 없는(MGR이 NULL인) 김민준이 빠지고 5행이 남습니다.
- 정하늘은 이번에는 남아서, GROUP BY가 20번·30번에 DEPTNO가 NULL인 그룹까지 3개를 만듭니다.
- HAVING에서 최댓값이 300인 NULL 그룹이 빠지고, ORDER BY가 TOP_SAL이 작은 30번부터 세웁니다.
3. 다음 쿼리는 Oracle에서 오류가 납니다. 까닭은 무엇이고, 어떻게 고치면 될까요?
SELECT ENAME,
SAL * 12 AS YEAR_SAL
FROM EMP
WHERE YEAR_SAL >= 6000;
정답
WHERE는 SELECT보다 먼저 처리됩니다. 그래서 WHERE를 처리할 때는 SELECT의 별칭 YEAR_SAL이 아직 없습니다. Oracle은 ORA-00904(invalid identifier) 오류를 냅니다. 별칭 대신 식을 그대로 쓰면 됩니다.
SELECT ENAME,
SAL * 12 AS YEAR_SAL
FROM EMP
WHERE SAL * 12 >= 6000;| ENAME | YEAR_SAL |
|---|---|
| 김민준 | 6240 |