[SQLD] ORDER BY

Shy·2024년 5월 20일

SQLD

목록 보기
15/23

ORDER BY

ORDER BY 절은 SQL 쿼리에서 결과 데이터를 정렬하는 데 사용된다. 특정 칼럼이나 표현식을 기준으로 데이터를 오름차순(ASC) 또는 내림차순(DESC)으로 정렬할 수 있으며, 정렬 방식은 기본적으로 오름차순이다. ORDER BY 절은 SQL 문장의 가장 마지막에 위치한다.

SELECT 칼럼명 [ALIAS명]
FROM 테이블명
[WHERE 조건식]
[GROUP BY 칼럼(Column)이나 표현식]
[HAVING 그룹조건식]
[ORDER BY 칼럼(Column)이나 표현식 [ASC 또는 DESC]];

1️⃣ 정렬 방식

  • 오름차순(ASC): 기본값이며, 생략할 수 있다.
  • 내림차순(DESC): 내림차순으로 정렬한다.

2️⃣ 예제

예제1

이름을 내림차순으로 정렬하는 쿼리문은 아래와 같다.

SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
ORDER BY PLAYER_NAME DESC;
선수명    포지션  백넘버
-----    -----  ----
히카르도   MF    10
황철민     MF    35
...

예제2

포지션을 내림차순으로 정렬 (ALIAS 사용)하는 쿼리문은 아래와 같다.

SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버
FROM PLAYER
ORDER BY 포지션 DESC;
-- 출력 결과
선수명    포지션    백넘버
------   ------  -----
정학범             173
차상광             186
...

3️⃣ NULL 값 처리

  • Oracle: NULL 값을 가장 큰 값으로 간주하여 오름차순 정렬 시 마지막에, 내림차순 정렬 시 처음에 위치시킨다.
  • SQL Server: NULL 값을 가장 작은 값으로 간주하여 오름차순 정렬 시 처음에, 내림차순 정렬 시 마지막에 위치시킨다.

4️⃣ 여러 칼럼을 기준으로 정렬

여러 칼럼을 기준으로 정렬할 때, 우선순위에 따라 정렬된다.
다음은, 키 큰 순서대로, 키가 같으면 백넘버 순으로 정렬하는 쿼리문이다.

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
...

5️⃣ 칼럼 순서를 이용한 정렬

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
...

6️⃣ 다양한 방법으로 정렬

칼럼명, 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
...

SELECT 문장 실행 순서

SQL의 SELECT 문장은 여러 절로 구성되며, GROUP BY와 ORDER BY가 함께 사용될 때의 실행 순서는 중요하다. 일반적으로 SQL 문장은 다음과 같은 순서로 실행된다:

  • FROM: 발췌 대상 테이블을 참조한다.
  • WHERE: 발췌 대상 데이터가 아닌 것은 제거한다.
  • GROUP BY: 행들을 소그룹화한다.
  • HAVING: 그룹핑된 값 중 조건에 맞는 것만 출력한다.
  • SELECT: 데이터 값을 출력 및 계산한다.
  • ORDER BY: 데이터를 정렬한다.

이 순서는 SQL 옵티마이저가 SQL 문장의 구문(SYNTAX)과 의미(SEMANTIC) 오류를 점검하는 순서이기도 하다. 예를 들어, FROM 절에 정의되지 않은 테이블의 칼럼을 WHERE, GROUP BY, HAVING, SELECT, ORDER BY 절에서 사용하면 오류가 발생한다.

실행 순서와 각 절의 역할

1. FROM 절

테이블이나 뷰를 지정하여 데이터를 가져온다.

SELECT EMPNO, ENAME FROM EMP

2. WHERE 절

조건에 맞는 행을 필터링한다.

SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO = 10

3. GROUP BY 절

행을 그룹화한다.

SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO

4. HAVING 절

그룹화된 데이터에 조건을 적용한다.

SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO HAVING COUNT(*) > 5

5. SELECT 절

최종적으로 출력할 칼럼을 지정한다.

SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO HAVING COUNT(*) > 5

6. ORDER BY 절

결과를 정렬한다.

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

1. ORDER BY 절에서 SELECT 절에 없는 칼럼 사용

SELECT EMPNO, ENAME FROM EMP ORDER BY MGR;

EMPNO, ENAMESELECT 했지만 MGR로 정렬이 가능하다.

-- 실행 결과
EMPNO ENAME
----  ------
7902  FORD
7788  SCOTT
...

2. 인라인 뷰에 정의된 SELECT 칼럼을 메인 쿼리에서 사용

SELECT EMPNO FROM (SELECT EMPNO, ENAME FROM EMP ORDER BY MGR);

인라인 뷰에서 정의된 칼럼은 메인 쿼리에서도 사용 가능.

3. 인라인 뷰에 미정의된 칼럼을 메인 쿼리에서 사용 ❌

SELECT MGR FROM (SELECT EMPNO, ENAME FROM EMP ORDER BY MGR);

서브쿼리의 SELECT 절에서 선택되지 않은 칼럼은 사용할 수 없음.

-- 실행 결과
ERROR: "MGR": 부적합한 식별자

4. GROUP BY 절 사용 시 SELECT 절에 일반 칼럼 사용

SELECT JOB, SAL FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY SAL;

SALGROUP BY 기준이 아니므로 오류 발생.

-- 실행 결과
ERROR: GROUP BY 표현식이 아니다.
  • GROUP BY 절에서 그룹핑된 칼럼만 SELECT 절에 사용할 수 있다.
  • GROUP BY 절에서 그룹핑되지 않은 칼럼은 집계 함수(Aggregate Function)와 함께 사용해야 합니다.

제대로 실행하려면, 아래와 같이 쿼리문을 바꿔야 한다. 아래는 MAX(집계 함수)와 함께 사용하여 쿼리문을 동작시킨 예이다.

SELECT JOB, MAX(SAL) FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY MAX(SAL);
-- 실행 결과
JOB        MAX(SAL)
---------- --------
CLERK      1300
MANAGER    2975
...

5. GROUP BY 절 사용 시 ORDER BY 절에 집계 칼럼 사용

SELECT JOB FROM EMP GROUP BY JOB HAVING COUNT(*) > 0 ORDER BY MAX(EMPNO), MAX(MGR), SUM(SAL), COUNT(DEPTNO), MAX(HIREDATE);
  • 그룹핑된 칼럼과 집계 함수를 ORDER BY 절에서 사용할 수 있다.
-- 실행 결과
JOB
------
MANAGER
PRESIDENT
...
profile
신입사원...

0개의 댓글