ORDER BY 절은 SQL 쿼리에서 결과 데이터를 정렬하는 데 사용된다. 특정 칼럼이나 표현식을 기준으로 데이터를 오름차순(ASC) 또는 내림차순(DESC)으로 정렬할 수 있으며, 정렬 방식은 기본적으로 오름차순이다. ORDER BY 절은 SQL 문장의 가장 마지막에 위치한다.
SELECT 칼럼명 [ALIAS명]
FROM 테이블명
[WHERE 조건식]
[GROUP BY 칼럼(Column)이나 표현식]
[HAVING 그룹조건식]
[ORDER BY 칼럼(Column)이나 표현식 [ASC 또는 DESC]];
이름을 내림차순으로 정렬하는 쿼리문은 아래와 같다.
SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
ORDER BY PLAYER_NAME DESC;
선수명 포지션 백넘버
----- ----- ----
히카르도 MF 10
황철민 MF 35
...
포지션을 내림차순으로 정렬 (ALIAS 사용)하는 쿼리문은 아래와 같다.
SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
ORDER BY 포지션 DESC;
-- 출력 결과
선수명 포지션 백넘버
------ ------ -----
정학범 173
차상광 186
...
여러 칼럼을 기준으로 정렬할 때, 우선순위에 따라 정렬된다.
다음은, 키 큰 순서대로, 키가 같으면 백넘버 순으로 정렬하는 쿼리문이다.
SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE HEIGHT IS NOT NULL
ORDER BY HEIGHT DESC, BACK_NO;
-- 실행 결과
선수명 포지션 백넘버 키
----- ----- ---- ---
서동명 GK 21 196
권정혁 GK 1 195
...
SELECT 절에서 칼럼 순서를 정수로 매핑하여 사용할 수 있다. 이는 칼럼명이 길거나 정렬 조건이 많을 경우 유용하지만, 유지보수성과 가독성이 떨어질 수 있다.
다음은, 백넘버 내림차순, 백넘버가 같은 경우 포지션, 포지션까지 같은 경우 선수명 순서로 정렬하는 쿼리문이다.
SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
WHERE BACK_NO IS NOT NULL
ORDER BY 3 DESC, 2, 1;
선수명 포지션 백넘버
------ ---- -----
뚜따 FW 99
쿠키 FW 99
...
칼럼명, ALIAS명, 칼럼 순서번호 등을 혼용하여 ORDER BY 절을 사용할 수 있다.
다음은, DEPT 테이블 정보를 부서명, 지역, 부서번호 내림차순으로 정렬하는 예제이다.
-- 칼럼명 사용
SELECT DNAME, LOC, DEPTNO
FROM DEPT
ORDER BY DNAME, LOC, DEPTNO DESC;
-- 칼럼명 + ALIAS명 사용
SELECT DNAME DEPT, LOC AREA, DEPTNO
FROM DEPT
ORDER BY DNAME, AREA, DEPTNO DESC;
-- 칼럼명 + ALIAS명 사용
SELECT DNAME, LOC AREA, DEPTNO
FROM DEPT
ORDER BY 1, AREA, 3 DESC;
-- 실행 결과
DNAME AREA DEPTNO
--------- ------- ------
ACCOUNTING NEW YORK 10
OPERATIONS BOSTON 40
...
SQL의 SELECT 문장은 여러 절로 구성되며, GROUP BY와 ORDER BY가 함께 사용될 때의 실행 순서는 중요하다. 일반적으로 SQL 문장은 다음과 같은 순서로 실행된다:
이 순서는 SQL 옵티마이저가 SQL 문장의 구문(SYNTAX)과 의미(SEMANTIC) 오류를 점검하는 순서이기도 하다. 예를 들어, FROM 절에 정의되지 않은 테이블의 칼럼을 WHERE, GROUP BY, HAVING, SELECT, ORDER BY 절에서 사용하면 오류가 발생한다.
테이블이나 뷰를 지정하여 데이터를 가져온다.
SELECT EMPNO, ENAME FROM EMP
조건에 맞는 행을 필터링한다.
SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO = 10
행을 그룹화한다.
SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO
그룹화된 데이터에 조건을 적용한다.
SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO HAVING COUNT(*) > 5
최종적으로 출력할 칼럼을 지정한다.
SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO HAVING COUNT(*) > 5
결과를 정렬한다.
SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO HAVING COUNT(*) > 5 ORDER BY COUNT(*) DESC
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO
--------------------------------------------------------------
7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800 | NULL | 20
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600 | 300 | 30
7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250 | 500 | 30
7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20
7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850 | NULL | 30
7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450 | NULL | 10
7788 | SCOTT | ANALYST | 7566 | 1987-07-13 | 3000 | NULL | 20
7839 | KING | PRESIDENT| NULL | 1981-11-17 | 5000 | NULL | 10
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500 | NULL | 30
7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30
7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000 | NULL | 20
7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300 | NULL | 10
SELECT EMPNO, ENAME FROM EMP ORDER BY MGR;
EMPNO, ENAME을 SELECT 했지만 MGR로 정렬이 가능하다.
-- 실행 결과
EMPNO ENAME
---- ------
7902 FORD
7788 SCOTT
...
SELECT EMPNO FROM (SELECT EMPNO, ENAME FROM EMP ORDER BY MGR);
인라인 뷰에서 정의된 칼럼은 메인 쿼리에서도 사용 가능.
SELECT MGR FROM (SELECT EMPNO, ENAME FROM EMP ORDER BY MGR);
서브쿼리의 SELECT 절에서 선택되지 않은 칼럼은 사용할 수 없음.
-- 실행 결과
ERROR: "MGR": 부적합한 식별자
SELECT JOB, SAL FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY SAL;
SAL은 GROUP BY 기준이 아니므로 오류 발생.
-- 실행 결과
ERROR: GROUP BY 표현식이 아니다.
제대로 실행하려면, 아래와 같이 쿼리문을 바꿔야 한다. 아래는 MAX(집계 함수)와 함께 사용하여 쿼리문을 동작시킨 예이다.
SELECT JOB, MAX(SAL) FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY MAX(SAL);
-- 실행 결과
JOB MAX(SAL)
---------- --------
CLERK 1300
MANAGER 2975
...
SELECT JOB FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY MAX(EMPNO), MAX(MGR), SUM(SAL), COUNT(DEPTNO), MAX(HIREDATE);
-- 실행 결과
JOB
------
MANAGER
PRESIDENT
...