database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 39312 게시물 읽기
No. 39312
컬럼을 파싱하여 order by 입니다.
작성자
sysopmin
작성일
2012-02-24 16:42ⓒ
2012-02-24 16:43ⓜ
조회수
4,822

안녕하세요.
oracle 11g R2 입니다.


현재 들어있는 데이터 중 한 컬럼만 파싱해서 나온 것중 각각 order by를 주려고자 합니다.
현 테이블에 별도 컬럼 추가해서 인덱스 달고 order by 하기에는 많은 어려움이 있어 할 수 없이
파싱해서 order by로 해야만 하는 상황입니다.

아래는 제가 작업하다 에러가 생겨 뭔가 좋은 방법이 있을 듯한데 생각이 안들어 문의를 드립니다.
문자+숫자+문자+숫자 등이 섞여있을 때 order by 입니다.


with t as (
            select 100 dep1, 200 dep2, 300 dep3, 400 dep4, '서리1길 1-3' addr from dual
  union all select 100     , 200     , 300     , 400     , '서리1길 1-2'      from dual
  union all select 100     , 200     , 300     , 400     , '156-1'            from dual
  union all select 100     , 200     , 300     , 400     , '서리11길 443'     from dual
  union all select 100     , 200     , 300     , 400     , '156-13'           from dual
  union all select 100     , 200     , 300     , 400     , '서리2길 2-4'      from dual
  union all select 100     , 200     , 300     , 400     , '156-21'           from dual
  union all select 100     , 200     , 300     , 400     , '서리4길 3-55'     from dual
  union all select 100     , 200     , 300     , 400     , '156-101'          from dual
  union all select 100     , 200     , 300     , 400     , '서리6길 44-6'     from dual
  union all select 100     , 200     , 300     , 400     , '서리5길 934-98'   from dual
  union all select 100     , 200     , 300     , 400     , '156'              from dual
  union all select 100     , 200     , 300     , 400     , '서리2길 1-356'    from dual
  union all select 100     , 200     , 300     , 400     , '서리1길 10-98'    from dual
  union all select 100     , 200     , 300     , 400     , '서리1길 1-345'    from dual
  union all select 100     , 200     , 300     , 400     , '봉천10길 1-98'    from dual
  union all select 100     , 200     , 300     , 400     , '봉천2길 1-945'    from dual
  union all select 100     , 200     , 300     , 400     , '봉천1길 10-10'    from dual
  union all select 100     , 200     , 300     , 400     , '봉천1길 1-10'     from dual
  union all select 100     , 200     , 300     , 400     , '1 서상로 1번지 1-10 우리길 5-2'   from dual
  union all select 100     , 200     , 300     , 400     , '13 서상로 94번지 1-10 우리길 5-2' from dual
  union all select 100     , 200     , 300     , 400     , '1 서상로 11번지 1-10 우리길 5-2'  from dual
  union all select 100     , 200     , 300     , 400     , '3 서상로 94번지 1-10 우리길 5-2'  from dual
  union all select 100     , 200     , 300     , 400     , '1 서상로 24번지 1-10 우리길 5-2'  from dual
)
select dep1, dep2, dep3, dep4, addr
  from (
    select dep1, dep2, dep3, dep4
          ,addr
          ,regexp_substr(addr
                        ,'[^[:digit:]]+'
                        ,1,1
           ) a01
          ,to_number(regexp_substr(addr
                        ,'[[:digit:]]+'
                        ,1,1
           )) a02
          ,regexp_substr(addr
                        ,'[^[:digit:]]+'
                        ,1,2
           ) a03
          ,to_number(regexp_substr(addr
                        ,'[[:digit:]]+'
                        ,1,2
           )) a04
          ,regexp_substr(addr
                        ,'[^[:digit:]]+'
                        ,1,3
           ) a05
          ,to_number(regexp_substr(addr
                        ,'[[:digit:]]+'
                        ,1,3
           )) a06
          ,regexp_substr(addr
                        ,'[^[:digit:]]+'
                        ,1,4
           ) a07
          ,to_number(regexp_substr(addr
                        ,'[[:digit:]]+'
                        ,1,4
           )) a08
      from t
  )
 order by dep1, dep2, dep3, dep4
         ,a01 nulls first, a02 nulls first, a03 nulls first, a04 nulls first
         ,a05 nulls first, a06 nulls first, a07 nulls first, a08 nulls first
;
 

위의 결과는 아래와 같습니다.
DEP1 DEP2 DEP3 DEP4     ADDR
===========================================
100 200 300 400    156
100 200 300 400    1 서상로 1번지 1-10 우리길 5-2                   -- 여기부터
100 200 300 400    1 서상로 11번지 1-10 우리길 5-2
100 200 300 400    1 서상로 24번지 1-10 우리길 5-2
100 200 300 400    3 서상로 94번지 1-10 우리길 5-2
100 200 300 400    13 서상로 94번지 1-10 우리길 5-2              -- 여기까지가 order by 비정상이네요.
100 200 300 400    156-1
100 200 300 400    156-13
100 200 300 400    156-21
100 200 300 400    156-101
100 200 300 400    봉천1길 1-10
100 200 300 400    봉천1길 10-10
100 200 300 400    봉천2길 1-945
100 200 300 400    봉천10길 1-98
100 200 300 400    서리1길 1-2
100 200 300 400    서리1길 1-3
100 200 300 400    서리1길 1-345
100 200 300 400    서리1길 10-98
100 200 300 400    서리2길 1-356
100 200 300 400    서리2길 2-4
100 200 300 400    서리4길 3-55
100 200 300 400    서리5길 934-98
100 200 300 400    서리6길 44-6
100 200 300 400    서리11길 443
===========================================

문자열이 "문자+숫자+문자+숫자 ..." 이런 정렬이면 위 쿼리로 잘 될듯한데
"숫자 + 문자 + 숫자 + 문자 .... " 이런 문자열이 있으면 order by 가 비정상으로 나옵니다.

뭔가 좋은 방법이 있으시면 말씀하여 주시면 감사하겠습니다.

감사합니다.

이 글에 대한 댓글이 총 4건 있습니다.

연속된 숫자가 5자리 이상은 없다고 가정하고
연속된 숫자를 5자리로 픽스시켜 정렬한다.
(예 : 1 ==> 00001, 100 ==> 00100)

SELECT *
  FROM t
 ORDER BY dep1, dep2, dep3, dep4
        , REGEXP_REPLACE(REGEXP_REPLACE(addr
          , '([0-9]+)', '00000\1')
          , '(0+)?([0-9]{5})', '\2')
;

마농(manon94)님이 2012-02-24 17:29에 작성한 댓글입니다.

답변 감사드립니다.

출력이 아래와 같이 구주소 번지-호로 된것이 먼저 출력되고 그외 숫자로 시작하는거 다음에
신주소 출력이 목표입니다. 아래와 같이 나오는 것이 본 취지입니다.

마농님의 간결한 소스 참조로 함 연구해 보도록 하겠습니다.  감사합니다.
===========================================
100 200 300 400    156
100 200 300 400    156-1
100 200 300 400    156-13
100 200 300 400    156-21
100 200 300 400    156-101
100 200 300 400    1 서상로 1번지 1-10 우리길 5-2  
100 200 300 400    1 서상로 11번지 1-10 우리길 5-2
100 200 300 400    1 서상로 24번지 1-10 우리길 5-2
100 200 300 400    3 서상로 94번지 1-10 우리길 5-2
100 200 300 400    13 서상로 94번지 1-10 우리길 5-2 
100 200 300 400    봉천1길 1-10
100 200 300 400    봉천1길 10-10
100 200 300 400    봉천2길 1-945
100 200 300 400    봉천10길 1-98
100 200 300 400    서리1길 1-2
100 200 300 400    서리1길 1-3
100 200 300 400    서리1길 1-345
100 200 300 400    서리1길 10-98
100 200 300 400    서리2길 1-356
100 200 300 400    서리2길 2-4
100 200 300 400    서리4길 3-55
100 200 300 400    서리5길 934-98
100 200 300 400    서리6길 44-6
100 200 300 400    서리11길 443
===========================================

 

sysopmin님이 2012-02-24 18:00에 작성한 댓글입니다. Edit

구주소(000-000 형태)인지 여부 판별하여 먼저 정렬 후 위와 같이 정렬

SELECT *
  FROM t
 ORDER BY dep1, dep2, dep3, dep4
        , CASE WHEN REGEXP_LIKE(addr, '^[0-9]+(-[0-9]+)?$') THEN 1 END
        , REGEXP_REPLACE(REGEXP_REPLACE(addr
          , '([0-9]+)', '00000\1')
          , '(0+)?([0-9]{5})', '\2')
;

마농(manon94)님이 2012-02-24 18:12에 작성한 댓글입니다.

마농님이 답을 바로 주셨었네요. ^^
감사합니다. 

제가 풀은 방법은 아래와 같습니다.
혹시나 다른분들에게도 참조가 될까 올립니다.
 

select dep1, dep2, dep3, dep4, addr
  from t
 order by dep1, dep2, dep3, dep4
         ,case when regexp_like(
                                   regexp_replace(addr,'-')
                                  ,'^[0-9]*$')
                    then 1
           end
         ,regexp_replace(
              regexp_replace(addr,'([0-9]+)','00000\1')
             ,'(0+)?([0-9]{5})','\2'
          )
;

 

sysopmin님이 2012-02-26 18:38에 작성한 댓글입니다.
이 댓글은 2012-02-26 18:39에 마지막으로 수정되었습니다. Edit
[Top]
No.
제목
작성자
작성일
조회
39315결재 할 순서대로 보여주기 [2]
바램
2012-02-25
4485
39314롱러닝 쿼리 진행률 알 수 있는 방법 있나요? [2]
슬라임
2012-02-24
3932
39313가로 데이터를 세로 형식으로
장형욱
2012-02-24
4056
39312컬럼을 파싱하여 order by 입니다. [4]
sysopmin
2012-02-24
4822
39311문자열에 &가 포함되니.. [1]
궁금이
2012-02-24
3600
39310테이블 속성 [1]
뉴질랜드목동
2012-02-24
3446
39309데이터 변화가 없는데, Snapshot too old (ORA-01555) 발생될까요? [1]
데니아
2012-02-23
4206
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.016초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다