본문 바로가기

DB/Oracle

한글 - 알파벳 - 숫자 순으로 정렬

 기본적으로 Order By를 이용하여 정렬하면 특수문자와 숫자 영문자가 섞이고 마지막으로 한글이 나온다.

하지만 요구사항에 따라 한글 - 알파벳 - 숫자 처럼 출력 순서를 바꿔야하는 경우가 있다.

간단하게 Order By Desc를 사용하면 좋으나 전부 역순으로 정렬되므로 요구사항에 맞지 않다.


 처음 떠오른 것은 UNION ALL을 이용해서 3번 SELECT 하는 것이 었으나, 마음에 들지 않는다. 두번째로 생각난 것은 CASE WHEN을 이용해 컬럼을 만들어 정렬하는 것이다. SELECT한 DATA로 결과를 만들고 정렬을 하기 때문에 속도면에서도 나쁘지 않다고 생각된다. 그래서 이것을 기준으로 필요한 것을 찾아보니 이미 해본 사람들이 있었다. ASCII() 오라클 함수를 이용한 구분인데 문자열이 들어가도 첫문자의 아스키값을 10진수로 보여준다. 이 기능을 이용하여 한글인 경우를 보면 45217 이상의 수가 나온다. 한글인 경우 범위가 상당히 모호한데, 인터넷의 내용과 다르게 범위가 정확히 몇인지 확인되지 않았다. 테스트를 해보니 그 이상의 값도 나왔기 때문이다. 한글의 시작은 'ㄱ'이고 끝은 '힣'이라 생각했으나 '힝'으로 나와있어 테스트를 해보니 '힏'이 더 크게 나오기도 했다. 엑셀 문서에서 한글문자를보니 마지막이 '힣'이였는데... 정확한 판단이 안서고 조사를 해봐야하나 항상 시간이 문제다. 그래서 결국 45217  넘으면 한글로 판단했다. 일본어의 히라가나는 4만번대였으나... 구조적인 문제로 구별할 방법이 없다. 


그래서 결국 다음과 같은 쿼리가 나온다


WITH TEST AS(

  SELECT '6666' AS NAME FROM DUAL UNION ALL

  SELECT '512' AS NAME FROM DUAL UNION ALL

  SELECT '0' AS NAME FROM DUAL UNION ALL

  SELECT '가나' AS NAME FROM DUAL UNION ALL

  SELECT 'A' AS NAME FROM DUAL UNION ALL

  SELECT 'B' AS NAME FROM DUAL UNION ALL

  SELECT 'a' AS NAME FROM DUAL UNION ALL

  SELECT 'C' AS NAME FROM DUAL UNION ALL

  SELECT '  C' AS NAME FROM DUAL UNION ALL

  SELECT 'd' AS NAME FROM DUAL UNION ALL

  SELECT '나' AS NAME FROM DUAL

)

SELECT NAME,

CASE WHEN ASCII(UPPER(NAME)) > 45217 THEN '1' -- 한글

WHEN ASCII(UPPER(NAME)) BETWEEN '65'  AND '90' THEN '2' -- 알파벳

WHEN ASCII(UPPER(NAME)) BETWEEN '48'  AND '57'  THEN '3' -- 숫자

ELSE '4' -- 기타

END AS SORT_CODE

FROM TEST

ORDER BY SORT_CODE ASC, NAME ASC


정렬을 해보면 한가지 문제를 더 발견할 수 있다. 알파벳 대문자와 소문자는 정렬이 따로 된다.

그래서 한가지 더 추가했다.


WITH TEST AS(

  SELECT '6666' AS NAME FROM DUAL UNION ALL

  SELECT '512' AS NAME FROM DUAL UNION ALL

  SELECT '0' AS NAME FROM DUAL UNION ALL

  SELECT '가나' AS NAME FROM DUAL UNION ALL

  SELECT 'A' AS NAME FROM DUAL UNION ALL

  SELECT 'B' AS NAME FROM DUAL UNION ALL

  SELECT 'a' AS NAME FROM DUAL UNION ALL

  SELECT 'C' AS NAME FROM DUAL UNION ALL

  SELECT '  C' AS NAME FROM DUAL UNION ALL

  SELECT 'd' AS NAME FROM DUAL UNION ALL

  SELECT '나' AS NAME FROM DUAL

)

SELECT NAME,

CASE WHEN ASCII(UPPER(NAME)) > 45217 THEN '1' -- 한글

WHEN ASCII(UPPER(NAME)) BETWEEN '65'  AND '90' THEN '2' -- 알파벳

WHEN ASCII(UPPER(NAME)) BETWEEN '48'  AND '57'  THEN '3' -- 숫자

ELSE '4' -- 기타

END AS SORT_CODE

FROM TEST

ORDER BY SORT_CODE ASC, UPPER(NAME) ASC


이정도면 1차 목표는 달성했다. 구지 한가지 더 문제라면 특수문자 처리인데, 이것도 방법이 없다. 처음부터 특수문자는 고려대상이 아니였기때문이다. 예로 '  C' 는 맨마지막으로 내려온다. 기타로 분류하는 수 밖에....



'DB > Oracle' 카테고리의 다른 글

DB에서 컬럼 순서 랜덤하게 가져오기  (0) 2015.08.05
오라클 포트 설정하기  (0) 2014.05.21
D-DAY 계산  (0) 2013.01.17
연속되는 숫자 만들기  (0) 2012.09.18
오라클 ORA-01476 에러  (0) 2011.11.11