인자값을 동적쿼리 말고 IN 조건 처리가 가능할 수 있으려나요? 0 6 224

by 메로나 [SQL Query] [2020.06.03 14:51:26]


지난번에 인덱스 타는거 관련해서 /*+USE_CONCAT*/ 관련 처리가 안먹혀서 이런 저런 생각을 해보다가
답변 주셨던 어떤 분의 말씀으로 넘어오는 인자 구조를 좀 바꿔서 받으면 어떠냐고 하신 답글이 있어서요
프로그램에서 인자로 넘어오는 데이터가  p_param = 'A,B,C' 입니다.
이걸 IN 조건에 어떻게 넣을 수 없을까요? 

    SELECT
        t.*
    FROM TBL t
    WHERE t.lot IN (
                        SELECT nvl2(p_param, trim(substr(wdata,instr(wdata, ',', 1, LEVEL) + 1,instr(wdata, ',', 1, LEVEL + 1) - instr(wdata, ',', 1, LEVEL) - 1))
                        , lh.lot) AS code_value  
                        FROM   
                        (SELECT ',' || p_param || ',' AS wdata FROM DUAL)
                        CONNECT BY LEVEL <= length(wdata) - length(REPLACE(wdata, ',')) - 1  
                   )

이런 구조로 되어 있습니다. 저 IN 조건 우측은 'A,B,C' 의 형태를 
    A
    B
    C

형태의 행으로 바꾸어주는 것이고 그걸 다시 IN 조건으로 되는건데요
저부분을 

    SELECT
        t.*
    FROM TBL t
    WHERE t.lot IN ('A','B','C')

고정으로 박아보면 무지 빠릅니다. 그런데 저 CONNECT BY를 넣으니 무진장 한없이 느려집니다.
그래서 지난번 답변에서 처럼 C# 프로그램에서 넘어오는 A,B,C 형태를 'A','B','C' 형태로 미리 파싱한 것처럼 바꾸서어 IN에 대입하는 식으로 해볼려는데요

동적 쿼리 말고 방법이 있을까요? 동적쿼리 사용이 여기서는 금지 되어 있습니다..
화면의 어떤 조건 항목들에 따라 달라져야 되어서요


 

by 메로나 [2020.06.03 15:15:17]

 

REGEXP_SUB()를 사용해서 아래와 같이 해봤는데도 

안되네요

p_param = ''A,B,C';

 

 

SELECT 
    /*+ USE_CONCAT */
    t.lot
FROM TBL t
WHERE 1=1
AND 
(
    (p_param IS NOT NULL)
    AND t.lot IN (
                    SELECT 
                        DECODE(REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL), NULL, t.lot, REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL))
                    FROM DUAL 
                    CONNECT BY REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL) IS NOT NULL                                            
                 )
)                 
OR
(
    (p_param IS NULL)
    AND t.from_dt >= p_from AND t.to_dt < p_to
)

 

 

p_param에 값이 있을경우는 p_param의 A,B,C 형태로 된 것을 IN 조건으로 걸어 조회되어야 되고

p_param의 값이 없다면 기간별로 p_from과 p_to의 값을 이용하여 범위검색을 해야 됩니다.

조건에 따라서 인덱스가 달라져야 되는데 현재 저 IN 부분에서 막히네요


by pajama [2020.06.03 15:58:38]

IN 절에 'A', 'B', 'C' 조건이라면 아래처럼 하시면 될듯합니다.

 

SELECT ...

IN 
(
select regexp_substr('A,B,C','[^,]+', 1, level) from dual
connect by regexp_substr('A,B,C', '[^,]+', 1, level) is not null
)

 


by 메로나 [2020.06.03 16:04:21]

아래와 같이 REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL)가 아닌 DECODE를 넣은것은

p_param에 아무 값이 안넘어 올경우에는 전체조회를 하기 위함입니다

p_param이 NULL일경우 t.lot을 가져오게 되고 그게 AND t.lot IN () 의 조건에 같게 되어 전체 검색이 되는거죠

DECODE(REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL), NULL, t.lot, REGEXP_SUBSTR(p_param, '[^,]+', 1, LEVEL))


by pajama [2020.06.03 16:25:49]

죄송합니다.. 같은내용을 쓴셈이네요.


by 마농 [2020.06.03 17:22:09]

UNION ALL 로의 분기는 고려 안하시나요? 꼭 OR 조건을 고집해야 하나요?


by 메로나 [2020.06.03 17:26:54]

SELECT 

* (범위인덱스)

FROM TBL

WHERE

    해당값의 유무가 TRUE

    범위로 검색

UNION ALL

SELECT 

* (아이템 인덱스)

FROM TBL

WHERE

    해당값의 유무가 FALSE

    아이템으로 검색

 

이렇게 얘기해봤는데 고객이 동적쿼리도 안돼,... 저거도 안된다고 하네요 ㅠ...ㅠ

화면도 그냥 조회성인 것 뿐인데... 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입