[간단한 트릭] SQL로 특정 데이터만 우선 정렬하기

2014-05-21 08:23:29에 작성됨 | PHP, MySQL, 프로그래밍

간혹 DB를 사용하는 어떤 프로그램에서 데이터별로 정렬을 해야하는데 특정 데이터만 골라 다른 데이터보다 우선 정렬을 해야 할 때가 있다. 예를 들어 숙박시설 예약 프로그램에서 접수받아서 관리 프로그램에서 날짜별로 정렬해서 예약 데이터를 보여주는데, 성수기때 예약 접수 데이터가 너무 많아서 오늘 예약 들어온 것을 처리하려면 페이지를 뒤로 가서 찾아야 하거나 검색을 하는 경우가 생긴다. 그외 여러가지가 있지만 우선 위의 상황을 가정한다.

만약 SQL Server, MySQL, Oracle의 booking_data란 테이블에 다음과 같은 테이블이 존재한다고 가정하고,
+————–+————-+
| Field | Type |
+————–+————-+
| seq | int(11) |
| bookers_name | varchar(32) |
| booked_room | int(5) |
| booked_date | varchar(12) |
+————–+————-+

그 테이블에 다음과 같은 데이터가 있다고 가정한다.

+—–+——————–+————-+————-+
| seq | bookers_name | booked_room | booked_date |
+—–+——————–+————-+————-+
| 1 | Aldrich Stauffman | 101 | 2013-06-30 |
| 2 | Ryan Lucas | 201 | 2013-06-31 |
| 3 | Dominique Lefebvre | 201 | 2013-06-31 |
| 4 | Reimund Heinzel | 301 | 2013-06-02 |
| 5 | Richard Taylor | 301 | 2013-07-02 |
+—–+——————–+————-+————-+

예를 들어 6월 31일에 데이터를 우선 정렬하고자 한다. 라이언 루카스와 도미니크 르페브르가 다른 세 사람의 예약건보다 최상위로 올라와야 한다. 단순히 날짜를 최근 순으로 정렬하게 된다면 리차드 테일러가 제일 처음 올라오게 될 것이고, 역순으로 정렬하면 독일인 두명이 제일 처음 올라온다.

[MySQL]

MySQL의 경우 내장 함수가 많은데, 여기서도 이걸 이용할 수 있다. 하는 방법은 단순히 order by 절에서 field 함수를 사용하면 된다.

field(필드명, 정렬데이터1[, 정렬데이터2 , …])

기존에 다음과 같은 쿼리가 있을 때

SELECT * FROM booking_data ORDER BY booking_date DESC;

다음처럼 추가한다.

SELECT * FROM booking_data ORDER BY field(booking_date,’2013-06-31′) desc, booking_date DESC;
[Oracle / SQL Server 공통]

반면 오라클은 저런 구문을 지원하지 않아 약간 꼼수를 써야 하는데, 이를 이용하면 쿼리가 길어질 수 있어 주의를 요한다. 정렬을 주는 방법은, CASE 구분을 사용하여 특정 데이터를 Alias로 임시 정렬 값을 부여한 뒤 그것을 기준으로 정렬해주면 된다. 다음과 같이 만들어 낼 수 있다. 대략 형식은

SELECT 늘_뽑던_대로, CASE WHEN 열 = 데이터 THEN 정렬_우선순위 [WHEN 열2 = 데이터2 THEN 정렬_우선순위2 […]] ELSE ‘0’ END Alias명 FROM 데이터가_있는_테이블 ORDER BY Alias명 [ASC|DESC] …
과 같은 형식. 예를 들어 기존에 다음과 같은 쿼리가 있을 때

SELECT * FROM booking_data ORDER BY booking_date DESC;

다음처럼 추가해준다.

SELECT *, CASE WHEN booking_date = ‘2013-06-31’ THEN ‘1’ ELSE ‘0’ END DATE_PRIORITY FROM booking_data ORDER BY DATE_PRIORITY DESC, booking_date DESC;

다만 쿼리가 너무 길어지기 때문에, 가능하다면 프로시져 형태로 만드는 것도 좋다.

위 두 방법으로 쿼리를 실행하면 다음과 같은 결과가 나온다. (Oracle이나 MSSQL방법을 사용하면 회색으로 처리된 열이 새로 출력된다.)

+—–+——————–+————-+————-+—————+
| seq | bookers_name | booked_room | booked_date | DATE_PRIORITY |
+—–+——————–+————-+————-+—————+
| 2 | Ryan Lucas | 201 | 2013-06-31 | 1 |
| 3 | Dominique Lefebvre | 201 | 2013-06-31 | 1 |
| 5 | Richard Taylor | 301 | 2013-07-02 | 0 |
| 1 | Aldrich Stauffman | 101 | 2013-06-30 | 0 |
| 4 | Reimund Heinzel | 301 | 2013-06-02 | 0 |
+—–+——————–+————-+————-+—————+

Leave a Reply

Your email address will not be published. Required fields are marked *