No. 10373


TIPS(21) : HIERARCHICAL QUERY DATA의 SORT와 ORDERING
====================================================

ORACLE 6에서의 HIERARCHICAL QUERY에서는 SORT를 하기 위한 ORDER BY 절을 사용
할 수 없었다. 그러나, ORACLE 7.1이상 VERSION에서는 USER-DEFINED STORED
PROCEDURE를 이용하여 HIERARCHY 순서로 출력되면서 ORDERING할 수 있게 되었다.

세계의 지역에 관한 자료를 예로 보자.

      CREATE TABLE UNIVERSE 
      ( PARENT VARCHAR2(30) REFERENCES UNIVERSE,  
      NAME  VARCHAR2(30) PRIMARY KEY ); 
      
     REM SOME TEST DATA 
     INSERT INTO UNIVERSE VALUES ( NULL, 'WORLD' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'WORLD', 'EUROPE' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'EUROPE', 'ENGLAND' ) ; 
     INSERT INTO UNIVERSE VALUES ( 'EUROPE', 'THE NETHERLANDS' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'EUROPE', 'GERMANY' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'WORLD', 'ASIA' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'ASIA', 'JAPAN' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'ASIA', 'CHINA' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'WORLD', 'AMERICA' ) ; 
     INSERT INTO UNIVERSE VALUES ( 'AMERICA', 'UNITED STATES' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'AMERICA', 'MEXICO' ) ; 
     INSERT INTO UNIVERSE VALUES ( 'WORLD', 'AFRICA' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'AFRICA', 'EGYPT' ) ;  
     INSERT INTO UNIVERSE VALUES ( 'AFRICA', 'MOROCCO' ) ; 

 


위의 자료를 다음과 같이 보고자 하는 경우
WORLD 
        AFRICA 
                EGYPT 
                MOROCCO 
        AMERICA 
                MEXICO 
                UNITED STATES 
        ASIA 
                CHINA 
                JAPAN 
        EUROPE 
                ENGLAND 
                GERMANY 
                THE NETHERLANDS 

만약,ORDER BY절이 없이 QUERY하면
     SELECT RPAD( ' ', LEVEL * 5 ) || NAME FROM UNIVERSE 
      CONNECT BY PRIOR NAME = PARENT START WITH PARENT IS NULL; 
다음과 같은 결과를 얻게 된다.     
    WORLD 
        EUROPE 
                ENGLAND 
                GERMANY 
                THE NETHERLANDS 
        ASIA 
                JAPAN 
                CHINA 
        AMERICA 
                UNITED STATES 
                MEXICO 
        AFRICA 
                EGYPT 
                MOROCCO 

만약, 위 문장에 ORDER BY 절을 사용하면

      SELECT RPAD( ' ', LEVEL * 5 ) || NAME FROM UNIVERSE 
      CONNECT BY PRIOR NAME = PARENT START WITH PARENT IS NULL  
      ORDER BY NAME; 

다음과 같은 원치 않는 결과를 얻게 된다.     
        AFRICA 
        AMERICA 
        ASIA 
                CHINA 
                EGYPT 
                ENGLAND 
        EUROPE 
                GERMANY 
                JAPAN 
                 MEXICO 
                MOROCCO 
                THE NETHERLANDS 
                UNITED STATES 
     WORLD 

7. 1이상 VERSION에서는 다음과 같이 USER DEFINED FUNCTION을  이용하여 원하는
   자료를 얻을 수 있다.

CREATE OR REPLACE FUNCTION UNIVERSESORTORDER( PKEY UNIVERSE.NAME%TYPE )  
     RETURN VARCHAR2 IS 
        PATH VARCHAR2(2000); 
     BEGIN 
        PATH := PKEY; 
        -- INSERT ALL PREVIOUS PARENT RECORDS LIKE A DIRECTORY STRUCTURE 
        -- E.G. WORLD/EUROPE/... 
        FOR CREC IN ( SELECT PARENT FROM UNIVERSE  
                      CONNECT BY PRIOR PARENT = NAME 
                      START WITH NAME = PKEY ) LOOP 
           PATH := CREC.PARENT || '/' || PATH; 
        END LOOP; 
        RETURN PATH; 
     END; 
     / 
      
SELECT SUBSTR( RPAD( ' ', LEVEL * 5) || NAME, 1, 40) "THE UNIVERSE" 
       FROM UNIVERSE 
       CONNECT BY PRIOR NAME = PARENT 
       START WITH PARENT IS NULL 
       ORDER BY UNIVERSESORTORDER( NAME ) ;