본문으로 건너뛰기

SELECT 문이 실행되는 순서

SQLD 목차SQL 기본레슨 20 / 35

목차

SQL은 SELECT부터 쓰지만, 처리는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순서로 합니다.

처리 순서를 알면 어느 절에서 무엇을 쓸 수 있는지 설명할 수 있습니다. 예를 들어 SELECT에서 붙인 별칭(alias)은 ORDER BY에서는 쓸 수 있지만 WHERE에서는 쓸 수 없습니다. 합계 같은 집계 결과로 거르는 조건은 WHERE가 아니라 HAVING에 써야 합니다. 두 규칙 모두 처리 순서에서 나옵니다. 그림의 쿼리는 SAL이 400 이상인 사원만 부서별로 합쳐, 합계가 500 이상인 부서를 합계가 큰 순서로 보여 줍니다.

7단계 중 1단계. SQL은 SELECT부터 쓰지만 처리는 FROM부터 시작합니다.

1FROM에서 ORDER BY까지

쓰는 순서는 SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY입니다. Oracle은 HAVING을 GROUP BY 앞에 써도 받지만, 처리 순서는 바뀌지 않습니다.

순서절하는 일그림의 쿼리에서
1FROM테이블을 가져옴EMP 6행
2WHERE행을 거름4행 남음
3GROUP BY행을 묶음그룹 3개
4HAVING그룹을 거름그룹 2개 남음
5SELECT그룹마다 한 줄2줄
6ORDER BY줄을 세움880, 520 순

WHERE는 행을 하나씩 보는 단계라 아직 그룹이 없습니다. 그래서 SUM(SAL) 같은 집계 함수는 WHERE에 쓸 수 없고, 묶은 다음인 HAVING에 씁니다. SAL이 300인 정하늘이 WHERE에서 빠지므로, DEPTNO가 NULL인 그룹도 생기지 않습니다.

2별칭을 쓸 수 있는 곳

별칭은 다섯째인 SELECT를 처리할 때 붙습니다. 앞서 처리되는 WHERE·GROUP BY·HAVING은 그 이름을 모르므로 식을 다시 써야 합니다. 그림의 HAVING이 TOTAL 대신 SUM(SAL)을 쓴 까닭입니다.

절처리 순서별칭(시험 기준)
WHERE2못 씀
GROUP BY3못 씀
HAVING4못 씀
ORDER BY6씀

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;
DEPTNOTOTAL
20880
10520

같은 조건을 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번 부서 한 줄만 남습니다.

DEPTNOTOTAL
10520
  • 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줄입니다.

DEPTNOTOP_SAL
30450
20470
  • 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;
ENAMEYEAR_SAL
김민준6240

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

SQLD 목차로