728x90
반응형

제 8절 ORDER BY 절


1. ORDER BY 정렬

  ORDER BY 절은 SQL 문장으로 조회된 데이터들을 다양한 목적에 맞게 특정 칼럼을 기준으로 정렬하여 출력하는데 사용한다.


SELECT 칼럼명 [ALIAS명]

FROM 테이블명

[WHERE 조건식]

[GROUP BY 칼럼이나 표현식]

[HAVING 그룹조건식]

[ORDER BY 칼럼이나 표현식 [ASC 또는 DESC]];


- ORDER BY 절에 칼럼명 대신 SELECT 절에서 사용한 별명 사용 가능

- 또한, 칼럼 순서를 나타내는 정수 사용 가능하나, 유지보수성이나 가독성이 떨어짐

- ORDER BY 절에서 칼럼명, 별명, 칼럼순서(정수)를 같이 혼용하는 것도 가능

- 기본적으로 오름차순 적용(ASC), 내림차순은 DESC

- SQL 문장 맨 마지막 위치

- 숫자형 데이터 타입은 오름차순으로 정렬했을 경우에 가장 작은 값부터 출력

- 날짜형 데이터 타입은 오름차순 정렬했을 경우 날짜 값이 가장 빠른 값이 먼저 출력

- Oracle은 NULL 값을 가장 큰값으로 간주, 오름차순 정렬 시 가장 마지막에 위치, 내림차순은 가장 위

- SQL Server는 NULL 값을 가장 작은값으로 간주, 오름차순 정렬 시 가장 상위에 위치


예제) ORDER BY 절의 예로 선수 테이블에서 선수들의 이름, 포지션, 백넘버를 출력하는데 선수들의 백넘버 내림차순, 백넘버가 같은 경우 포지션, 포지션까지 같은 경우 선수명 순서로 출력, BACK_NO가 NULL인 경우는 제외하고, 칼럼명이나 ALIAS가 아닌 칼럼 순서를 매핑하여 사용


SELECT PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버

FROM PLAYER

WHERE BACK_NO IS NOT NULL

ORDER BY 3 DESC, 2, 1;





2. SELECT 문장 실행 순서


5. SELECT 칼럼명 [별명]

1. FROM 테이블명

2. WHERE 조건식

3. GROUP BY 칼럼이나 표현식

4. HAVING 그룹조건식

6. ORDER BY 칼럼이나 표현식;



발췌 대상 테이블을 참조하여 WHERE 조건에 맞지 않는 데이터는 제거한다. 그 다음 행들을 소그룹화 한다. 소그룹화 된 행들을 조건에 맞는 것만 출력한다. 그리고서 조건에 맞는 행들 중 선택된 칼럼들만 뽑아낸다. 마지막으로 뽑아낸 칼럼들을 정렬한다. 


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

  그러나 ORDER BY 절에는 SELECT 목록에 나타나지 않은 문자형 항목이 포함될 수 있다. 단 SELECT DISTINCT를 지정하거나, SQL 문장에 GROUP BY 절이 있거나 또는 SELECT 문에 UNION 연산자가 있으면 열 정의가 SELECT 목록에 표시되어야한다.

  이 부분은 관계형 데이터베이스가 데이터를 메모리에 올릴 때 행 단위로 모든 칼럼을 가져오게 되므로, SELECT 절에서 일부 칼럼만 선택하더라도 ORDER BY 절에서 메모리에 올라와 있는 다른 칼럼의 데이터를 사용할 수 있다. 


예제)

SELECT EMPNO, ENAME

FROM EMP

ORDER BY MGR;


  그러나 서브쿼리의 SELECT 절에서 선택되지 않은 칼럼들은 계속 유지되는 것잉 아니라 서브쿼리의 범위를 벗어나면 더 이상 사용할 수 없게 된다.

  GROUP BY 절에서 그룹핑 기준을 정의하게 되면, 데이터베이스는 일반적으로 SELECT 문장 처럼 FROM 절에 정의된 테이블의 구조를 그대로 가지고가는 것이 아니라, GROUP BY 절의 그룹핑 기준에 사용된 칼럼과 집계 함수에 사용될 수 있는 숫자형 데이터 칼럼들의 집합을 새로 만든다.

  GROUP BY 절을 사용하게 되면 그룹핑 기준에 사용된 칼럼과 집계 함수에 사용될 수 있는 숫자형 데이터 칼럼들의 집합을 새로 만드는데, 개별 데이터는 필요없으므로 저장하지 않는다. GROUP BY 이후 수행절인 SELECT 절이나 ORDER BY 절에서 개별 데이터를 사용하는 경우 에러가 발생된다.

  결과적으로 SELECT 절에서는 그룹핑 기준과 숫자 형식 칼럼의 집계 함수를 사용할 수 있지만, 그룹핑 기준 외의 문자 형식 칼럼은 정할 수 없다. 


예제)

SELECT JOB

FROM EMP

GROUP BY JOB

HAVING COUNT(*) > 0

ORDER BY MAX(EMPNO), MAX(MGR), SUM(SAL), COUNT(DEPTNO), MAX(HIREDATE);


  SELECT SQL에서 GROUP BY 절이 사용되었기 때문에 SELECT 절에 정의하지 않은 MAX, SUM, COUNT 집계 함수도 ORDER BY 절에서 사용할 수 있는 것을 확인 할 수 있다.






3. Top N 쿼리


ROWNUM

  Oracle에서 순위가 높은 N개의 로우를 추출하기 위해 ORDER BY 절과 WHERE 절의 ROWNUM 조건을 가팅 사용하는 경우가 있는데, 이 두조건으로는 원하는 결과를 얻을 수 없다. Oracle의 경우 정렬이 완료된 후 데이터의 일부가 출력되는 것이 아니라, 데이터의 일부가 먼저 추출된 후 데이터에 대한 정렬 작업이 일어나게 되므로 주의해야한다.


예제) 사원 테이블에서 급여가 높은 3명만 내림차순으로 출력, 잘못사용된 SQL의 사례


SELECT ENAME, SAL

FROM EMP

WHERE ROWNUM < 4

ORDER BY SAL DESC;


ENAME    SAL

-----    ----

ALLEN    1600

WARD    1250

SMITH    800


  이 실행결과는 급여가 상위인 3명을 출력한 것이 아니라, 급여 순서에 상관없이 무작위로 추출된 3명에 한해서 급여를 내림차순으로 정렬한 결과이므로 원하는 결과를 출력한 것이 아니다.


  ORDER BY 절이 없으면 Oracle의 ROWNUM 조건과 SQL Server의 TOP 절은 같은 성능을 보이게 된다. 그렇지만 ORDER BY 절이 사용되는 경우, 오라클은 ROWNUM의 조건을 ORDER BY 절보다 먼저 처리되는 WHERE 절에서 처리하므로, 정렬 후 원하는 데이터를 얻기 위해서는 인라인뷰를 사용하여 아래와 같이 데이터 정렬을 먼저 수행한 후, 메인 쿼리에서 ROWNUM 조건을 사용해야한다.


  즉 오라클에서는 ORDER BY 절이 사용되는 경우, ROWNUM의 조건을 제일 먼저 처리하기 때문에 위와 같이 무작위로 상위 3명을 추출한 뒤, 정렬을 하게되는 것이다. 그래서 인라인뷰를 사용하여 처리해야함.


SELECT ENAME, SAL

FROM (SELECT ENAME, SAL

FROM EMP

ORDER BY SAL DESC)

WHERE ROWNUM < 4;




TOP()

  반면 SQL Server는 TOP 조건을 사용하게 되면 별도 처리 없이 관련 ORDER BY 절의 데이터 정렬 후 원하는 일부 데이터만 쉽게 출력할 수 있다.


TOP (Expression) [PERCENT][WITH TIES]


  TOP 절을 사용하여 결과 집합으로 반환되는 행 수를 제한할 수 있다. WITH TIES 옵션은 ORDER BY 절의 조건 기준으로 TOP N의 마지막 행으로 표시되는 추가 행의 데이터가 같을 경우 N+동일 정렬 순서 데이터를 추가 반환하도록 지정하는 옵션이다.


즉, 동일 수치의 데이터를 추가로 더 추출하는 것이다. 


예제) 

SELECT TOP(2) WITH TIES ENAME, SAL

FROM EMP

ORDER BY SAL DESC;


ENAME    SAL

-----    ----

KING      5000

SCOTT    3000

FORD     3000


728x90
반응형

'Computer Science > SQL-D' 카테고리의 다른 글

[SQLD] 21. 표준 조인(STANDARD JOIN)  (0) 2016.08.24
[SQLD] 20. 조인(JOIN)  (2) 2016.08.18
[SQLD] 18. GROUP BY, HAVING 절  (0) 2016.08.18
[SQLD] 17. 함수 (Function)  (0) 2016.08.18
[SQLD] 16. WHERE 절  (0) 2016.08.16