결과를 제어하여 데이터를 제공할 수 있다.
2.1 지정한 순서대로 쿼리 결과 반환하기
ORDER BY 절을 사용한다.
select ename, job, sal
from emp
where deptno = 10
order by sal asc
부서 10에 속한 사원을 sal (급여) 기준으로 오름차순으로 정렬할 수 있다. 기본적으로 ASC 오름차순으로 정렬되고, 내림차순은 DESC를 지정해야 한다.
열의 이름 대신 번호로 대체 할 수 있다. 1에서 시작하여 오른 쪽 순서대로 증가한다. sal은 세번째이므로 3으로 대체할 수 있다.
select ename, job, sal
from emp
where deptno = 10
order by 3 desc
2.2 다중 필드로 정렬하기
deptno 기준으로는 오름차순 asc 으로 정렬한다음, sal 급여 내림차순 desc 로 정렬하려고 한다. ORDER BY 절에서 쉼표로 구분하여 정렬할 여러 열을 나열하면 된다.
select empno, deptno, sal, ename, job
from emp
order by deptno, sal desc
ORDER BY의 우선순위는 왼쪽에서 오른쪽이다. 따라서 deptno asc(생략) 이 우선이 되는 것이다.
추가로, SELECT 목록에 없는 열로 정렬할 수도 있는데, GROUP BY나 DISTNCT를 사용할 때는 SELECT 목록에 없는 열 기준으로 정렬할 수 없다.
2.3 부분 문자열로 정렬하기
문자열의 특정 부분을 기준으로 쿼리 결과를 정렬하려고 한다. job 열의 마지막 두 문자를 기준으로 정렬하려고 한다.
//DB2, MySQL, Oracle, PostgreSQl
select ename, job
from emp
order by substr(job, length(job)-1)
//SQL Server
select ename, job
from emp
order by substring(job, len(job)-1, 2)
부분 문자열 substring 함수를 사용하면 된다. 두 문자를 기준으로 정렬하려면 문자열의 길이를 찾아 1을 뺀다. 그래서 시작 위치가 문자열의 마지막에서 두 번째 문자가 되는 것이다. 함수는 시작 위치 이후의 모든 문자를 가져오므로 마지막 두 문자로 정렬할 수 있게 된다.
2.4 혼합 영숫자 데이터 정렬하기
REPLACE, TRANSLATE 함수를 사용하여 정렬할 문자열을 수정한다.
The SQL TRANSLATE() function replaces a sequence of characters in a string with another sequence of characters. The function replaces a single character at a time.
문자열의 문자 시퀀스를 다른 문자 시퀀스로 바꾸고, 한번에 하나의 문자를 바꾼다.
ex)TRANSLATE(data, ‘abc’, ‘def’) 는 a →d, b→e, c→f 로 바뀐다.
TRANSLATE(변경할 열, '사용하고 있는 문자', '대체될 문자')
REPLACE(변경할 열, '바꾸려는 문자열', '바뀔 문자열')
create view v
as
select ename||' '||deptno as data
from emp
select * from V
DATA
-----------
SMITH 20
ALLEN 30
WARD 30
//Oracle, SQL Server, PostgreSQL
/*
replace(translate(data, '0123456789', '##########'), '#', '')
=> translate에 의해 숫자가 #으로 변환
=> replace에 의해 #이 ''로 변환해서 없어짐
=> 이름만 남음
*/
//ename 정렬하기
select data
from V
order by replace(translate(data, '0123456789', '##########'), '#', '')
//depno 정렬하기
/*
data를 이름을 ''으로 변환하므로 숫자만 남음
*/
select data
from V
order by replace(data,
replace(translate(data, '0123456789', '##########'), '#', ''),
'')
//DB2
//ename 정렬하기
select *
from (
select ename||' '||cast(deptno as char(2)) as data from emp
) V
order by replace(translate(data, '##########', '0123456789'), '#', '')
//depno 정렬하기
/*
data를 이름을 ''으로 변환하므로 숫자만 남음
*/
select *
from (
select ename||' '||cast(deptno as char(2)) as data from emp
) V
order by replace(data,
replace(translate(data, '##########', '0123456789'), '#', ''),
'')
DB2는 translate()의 순서가 다르니 주의해야 하고, deptno을 char로 캐스트해야한다. 뷰를 반드는 대신에 인라인 뷰를 사용해야 하는 것이다.
*MySQL은 TRANSLATE 함수를 지원하지 않으므로 이 문제에 대한 해법을 제공할 수 없다.
2.5 정렬할 때 null 처리하기
RDBMS가 Oracle처럼 null이 아닌 값을 수정하지 않고도 Null 값을 정렬하는 방법을 제공하지 않는 한, 보조 열이 필요하다.
//DB2, MYSQL, PostgreSQL, SQL Server
/*
NULL이 아닌 COMM을 우선 오름차순 정렬하고, NULL은 마지막에 나타냄
*/
select ename, sal, comm
from (
select ename, sal, comm
case when comm is null then 0 else 1 end as is_null
from emp
) X
order by is_null desc, comm
//Oracle
/*
NULL이 아닌 COMM을 우선 오름차순 정렬하고, NULL은 마지막에 나타냄
*/
select ename, sal, comm
from emp
order by comm nulls last
CASE를 사용하여 comm이 null인 경우 0 그렇지 않으면 1로 바꿔주고 is_null이라고 별칭을 준다. 그리고 is_null을 내림차순으로 정렬하면 1부터 정렬되고, 그것은 comm이 null이 아닌 값을 의미한다. 그리고 comm을 오름차순으로 정렬해주는 것이다.
2.6 데이터 종속 키 기준으로 정렬하기
일부 조건식을 기반으로 정렬하려고 한다. 예를들어 JOB이 ‘SALESMAN’이면 COMM기준으로 정렬하고, 그렇지 않으면 SAL 기준으로 정렬하고자 한다.
ENAME SAL JOB COMMM
------ ------ ---- ----------
ANAME 1500 SALESMAN 0
BNAME 1600 SALESMAN 300
CNAME 800 CLERK
select ename, sal, job, comm
from
order by case when job = 'SALESMAN' then comm else sal end
아래와 같이 사용하여도 된다.
select ename, sal, job, comm
case when job = 'SALESMAN' then comm else sal end as ordered
from emp
order by 5