SQL Cook: 2.6장 데이터 종속 키 기준으로 정렬하기

0

SQL_COOK

목록 보기
8/35
post-thumbnail

Q. 일부 조건식을 기반으로 정렬하려고 한다

예를 들어, 'JOB'이 'SALESMAN'이면 'COMM'기준으로 정렬하고, 그렇지 않으면 'SAL'을 기준으로 정렬하고자 한다. 반환하려는 결과셋을 확인하고 해법을 생각해본다.

A. ORDER BY절에서 CASE를 사용한다

CASE WHEN THEN END 구문은 정말 함수처럼 작동한다. 아마 다른 내장 함수들도 그렇게 작동할 것 같다. SELECT절에서 열을 추가하는 방법으로 사용했는데, 여기서는 `ORDER BY절에서도 사용하고 있음을 설명해주고 있다.

/* ORACLE */
select ename, sal, job, comm
	from emp
	order by case when job='salesman' then comm
	else sal
	end;
>>
ENAME	SAL		JOB			COMM
SMITH	800		CLERK	 	 - 
JAMES	950		CLERK	 	 - 
ADAMS	1100	CLERK	 	 - 
MARTIN	1250	SALESMAN	 1400
WARD	1250	SALESMAN	 500
MILLER	1300	CLERK	 	 - 
TURNER	1500	SALESMAN	 0
ALLEN	1600	SALESMAN	 300
CLARK	2450	MANAGER	 	 - 
BLAKE	2850	MANAGER	 	 -
JONES	2975	MANAGER	 	 - 
FORD	3000	ANALYST	 	 - 
SCOTT	3000	ANALYST	 	 - 
KING	5000	PRESIDENT	 - 

그런데 Oracle과 Maria에서의 결과가 다르게 나온다...

/* Maria */
select ename, sal, job, comm
    from emp
    order by case when job='salesman' then comm
    else sal
    end;
>>
+--------+------+-----------+------+
| ename  | sal  | job       | comm |
+--------+------+-----------+------+
| TURNER | 1500 | SALESMAN  |    0 |
| ALLEN  | 1600 | SALESMAN  |  300 |
| WARD   | 1250 | SALESMAN  |  500 |
| SMITH  |  800 | CLERK     | NULL |
| JAMES  |  950 | CLERK     |    0 |
| ADAMS  | 1100 | CLERK     | NULL |
| MILLER | 1300 | CLERK     | NULL |
| MARTIN | 1250 | SALESMAN  | 1400 |
| CLARK  | 2450 | MANAGER   | NULL |
| BLAKE  | 2850 | MANAGER   | NULL |
| JONES  | 2975 | MANAGER   | NULL |
| SCOTT  | 3000 | ANALYST   | NULL |
| FORD   | 3000 | ANALYST   | NULL |
| KING   | 5000 | PRESIDENT | NULL |
| IREN   | 9000 | TESTER    | 9000 |
+--------+------+-----------+------+

일단 책에서 나온 결과셋은 Maria와 일치한다.
Oracle에서 왜 다른 결과가 나오는지는 알 수 없다.
Oracle Live를 쓰고 있기 때문에, 지난 세션에서 뭔가를 잘못 건드린 것 같기도 하다.
이 부분은 시간이 넉넉할 때 다시 확인해보기로 하겠다.

책의 결과셋과 일치한 Maria로 다음을 진행해본다.

Ref. CASE식을 사용하여 결과의 정렬 방식을 동적으로 변경할 수 있다 / ORDER BY에 전달된 값을 다음 쿼리에서 확인하라

/* 동적 정렬 */
select ename, sal, job, comm,
	# 아래의 CASE구문에서 다섯 번째 칼럼을 동적으로 생성하고
    case when job='salesman' then comm
    else sal end as ordered
    from emp
    # 아래의 ORDER BY절에서 다섯 번째 칼럼을 기준으로 했다
    order by 5

매우 참신한 풀이다!


2. 7장 마치며

쿼리 결과의 정렬은 SQL의 핵심기술 중 하나이다. ORDER BY절은 매우 강력하지만 해법에서의 미묘한 차이를 이해해야 한다.


정리

  • 동적 정렬
    • 동적인 정렬은 SELECT구문에 CASE WHEN THEN END구문을 사용하여 보조 열을 하나 생성하여 정렬했다
    • SELECT절에 붙어있으므로 조회하려는 열이 좀 더 명확해지는 느낌을 받았다

  • 조건절에 CASE WEHN THEN END구문의 반환값 사용
    • ORDER BY구문에 CASE WHEN THEN END구문을 사용하여 정렬한 방법이 전형적인 것 같기도 하다
    • 정렬하고자 하는 칼럼명을 마지막에 명확하게 밝히는 느낌이다
    • 다만 꼬리가 너무 늘어지는 느낌? 마지막이 조금 느리고 무거워지는 느낌?
      ...

아직 어떤 방법이 어떤 경우에 더 유리한지는 잘 모르겠다. 동적 정렬은 SELECT절이 조금 길어지면서 ORDER BY절로 열의 인덱스까지 정해줘야 하는 단점이 있는 것 같다.

ORDER BY절이 해법에서 미묘한 차이를 보이며, 이를 이해해야 한다고 나와 있는데 아직은 정말 잘 모르겠다 ㅠㅠ

공부가 많이 필요하다.


0개의 댓글