SELECT * FROM PRODUCT
WHERE ((PARAM_BRANDCODE IS NOT NULL and (BRANDCODE IN ('B001','B002'))) OR (PARAM_BRANDCODE IS NULL and(1=1)));
역시나 저번 질문이랑 비슷한건데 제가 응용력이 없는지 이걸 or절 안쓰고 어떻게 튜닝해야할지 잘모르겠네요
PARAM_BRANDCODE 브랜드 코드 파라미터입니다 'B001,B002' 이런식으로 여러 개 동시에에 넘길수도 있고 아무것도 안넘길수도 있습니다
아무것도 안넘기면 전체검색(1=1)이고 넘어가면 in절로 검색해야되는데 이게 or구문안쓰고 어떻게 가능할까요? 실행계획봐도 OR절은 풀스캔되서 코스트가 대박이라 영 별로네요 매번 도움만 받는거같아서 죄송하네요 ㅜ
UNION ALL 라는 대체법이 있는건 알지만 안그래도 긴 쿼리가 너무 길어져서 일단 보류중입니다
파라미터가 구분자를 포함한 여러값이 넘어 오네요.
이 경우 동적쿼리를 사용하지 않고서는 IN 조건 사용이 불가능 합니다.
조건을 brandcode IN (param_brandcode) 처럼 사용시에 동작되는 것은 다음과 같습니다.
- 원하는 것 : brandcode IN ('B001','B002')
- 실제 동작 : brandcode IN ('B001,B002') -- 하나의 값으로 인식 --
문자열 비교 방식으로 풀 수는 있습니다만 인덱스 이용 못하죠.
- param_brandcode LIKE '%'||brandcode||'%'
- INSTR(param_brandcode, brandcode) > 0
문자열을 분리해서 IN 절에 넣는 방식도 고려해 볼 수는 있습니다.
- brandcode IN (SELECT SUBSTR(param_brandcode, (LEVEL-1)*5+1, 4) FROM dual CONNECT BY LEVEL <= (LENGTH(param_brandcode)+1)/5)
USE_CONCAT 힌트로 실행계획을 분리시켜보세요.
SELECT /*+ USE_CONCAT */ * FROM product WHERE ( (param_brandcode IS NULL) OR (param_brandcode IS NOT NULL AND brandcode IN (SELECT SUBSTR(param_brandcode, (LEVEL-1)*5+1, 4) FROM dual CONNECT BY LEVEL <= (LENGTH(param_brandcode)+1)/5 ) ) ) ;
동적쿼리로 사용안하고
BRANDCODE IN (SELECT regexp_substr(UPPER(''),'[^/]+', 1, level) from dual connect by regexp_substr(UPPER(''), '[^/]+', 1, level) is not null )
이 방법으로 했습니다 오라클을 만진지 얼마 안되서 여기저기 찾아가면서 했습니다 ㅠ
마농님이 말씀해주신
brandcode IN (SELECT SUBSTR(param_brandcode, (LEVEL-1)*5+1, 4)
FROM dual
CONNECT BY LEVEL <= (LENGTH(param_brandcode)+1)/5
이방법이랑 비슷하겠군요