범위 SQL 검색에 대해서 0 8 2,120

by 야신 [PL/SQL] 범위 [2013.11.08 10:52:45]


조건에 가장 정확한 것을 기준으로 없으면 상위로 올라가는 찾는 로직에 대해 문의합니다.
아래와 같은 데이타에 인덱스가 COUNTRY, DO, SI 순으로 생성되어 있을 경우
조건이 DO 와 SI 를 파리미터로 받는 다고 하면
WITH T AS( SELECT '대한민국' AS COUNTRY
     , '경기도' AS  DO
     , '평택' AS SI
  FROM DUAL
UNION ALL
SELECT '대한민국' AS COUNTRY
     , '경기도' AS  DO
     , '화성' AS SI
  FROM DUAL)
SELECT *
FROM T 
WHERE COUNTRY = '대한민국'
  AND DO = '경기도'   
  AND SI = '?'
1) 옛날(?) 방식 - 오라클에서 권하는 방식은 아니지만 논리적으로 왠지 명확하다고 할까...
  먼저 COUNT 해서 개수를 구한뒤 가져오는 방식, 
  제가 생각하는 단점은 SQL 을 여러번 실행한다. 소스기 길어진다.
  장점은 가장 처음에 걸릴경우 가장 인덱스를 잘 탈수도 있다고 생각합니다.
  
  SELECT COUNT(*)
    INTO v_count
    FROM T
    WHERE COUNTRY = '대한민국'
      AND DO = '경기도'   
      AND SI = '화성';
      
   IF v_count > 0 THEN
    SELECT si
      INTO v_region
      FROM T
      WHERE COUNTRY = '대한민국'
        AND DO = '경기도'   
        AND SI = '화성';   
   ELSE
   
      SELECT count(*) 
        INTO v_region
        FROM T
        WHERE COUNTRY = '대한민국'
          AND DO = '경기도';      
          
          ...
          ..
   END IF;
   
2) 1방식의 변형으로 사용하는 방식
  begin
    SELECT si
      INTO v_region
      FROM T
      WHERE COUNTRY = '대한민국'
        AND DO = '경기도'   
        AND SI = '화성';   
   exception
     when no_data_found then
     
      SELECT do
        INTO v_region
        FROM T
        WHERE COUNTRY = '대한민국'
          AND DO = '경기도' ;
          
    exception
      when others then
        null;
    end;        
     
    
   
3) 제가 쓰는 방식은 아래와 같은 방식을 사용하는데 인덱스를 범위로 타게 되고 그룹핑 함수 사용에 따른
리소스 사용이 있는데 여러분은 어떤 방식을 즐겨 사용하시나요?

 SELECT NVL(MAX(DECODE(SI,'화성', SI)),MAX(DO))
    INTO v_region
    FROM T
    WHERE COUNTRY = '대한민국'
      AND DO = '경기도'

더 좋은 방식이 있으면 공유 부탁드려요.
by 용근님 [2013.11.08 13:55:57]

저라면 화면에서 COUNTRY를 필수로 받겠습니다.  - -; 뻘글이였습니다

by 우리집아찌 [2013.11.08 14:02:25]
저라면 느려도 그냥 쓰라고 합니다....ㅡㅡ;

by 야신 [2013.11.08 14:08:39]
//용근님
COUNTRY 는 필수고 DO 와 SI 를 대상으로 
입력받는  SI 와 같은 대상이 있으면 SI 를 없으면 DO 에서 찾아오는 거에요 
ㅡ_ㅡ;;

// 우리집 아찌님
저도 그러고 싶은데 하루에 백만건 이상을 저런 로직을 이용한 함수로 처리하다 보니...
속도 느리다고 컴플레인이 들어오고 어쩔수 없이 속도를 최대로 고려한 프로그램을 짜다 보니 흐엉~ .
ㅠㅠ.

by 마농 [2013.11.08 14:20:59]
SELECT region
  FROM (SELECT si region
          FROM t
         WHERE country = '대한민국'
           AND do = '경기도'
           AND si = '화성'
         UNION ALL
        SELECT do
          FROM t
         WHERE country = '대한민국'
           AND do = '경기도'
         UNION ALL
        SELECT country
          FROM t
         WHERE country = '대한민국'
        )
 WHERE ROWNUM <= 1
;

by 야신 [2013.11.08 14:43:02]
//마농님~
마농님의 소스가 이전에 사용하던 부분인데요
union all 로 묶여 있어 위와 같이 순차적으로 풀어버린것인데 - 앞에서 걸리면 바로 끝나니까 - 
속도면에서 어떤것이 나을가요?

by 마농 [2013.11.08 14:49:14]
ROWNUM <= 1 이 조건이 있어서 전혀 부담스럽지 않습니다.
앞에서 결과가 나온다면 뒤쪽 쿼리는 수행되지 않는다고 보시면 됩니다.

by 야신 [2013.11.08 16:19:29]
// 마농님께
충격적인 사실을 오늘에야 알았네요 지금까지 잘못 알고 있었네요. ㅠㅠ
union all 로 묶으면 조건에 맞으면 뒤에것은 실행이 안된다는 것을 몰랐네요.
절차적으로 짤 필요가 없겠네요.
요즘 들어 멘붕에 자주 빠집니다.

정말 감사합니다.

by feelie [2013.11.08 15:43:37]

unoin all,  rownum 의 조합이 있었군요...
union all 앞의 결과가 나온다면 뒤쪽쿼리는 수행하지 않는다...
실행계획을 보니 뒤쪽 쿼리에 대하여 오퍼레이션은 있는데...
A-Rows는 0 으로 표현되네요...(수행안하는것으로 판단하신 근거라 생각되네요)
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입