쿼리 질문, WHERE COL_A IN ('A%', 'B%', 'C%') 같이 조회 방법 문의 0 9 1,502

by 네오스타 [2016.08.04 20:37:50]


안녕하세요.

좋은 방법이 생각이 안나서 혼자 고민하다가

고수분들께 문의드리게 되었습니다.

 

WHERE COL_A IN ('A%', 'B%', 'C%') 같이 조회하고 싶습니다.

 

하기는 데이터입니다.

 

기존    변경 
100만건   50건   100만건   50건
TABLE_A   TABLE_B   TABLE_A   TABLE_B
COL_A   COL_B   COL_A   COL_B
T01   T01   T01-00   T01
T01   T02   T01-01   T02
T02   T05   T02-02   T05
T02       T02-03    
T02       T02-GG    
T03       T03-AA    
T03       T03-DSKW    
T03       T03-2003    
T03       T03-1    
T04       T04-053    
T04       T04-052    
T05       T05-051    

 


SELECT * 
  FROM TABLE_A 
 WHERE COL_A IN (SELECT COL_B FROM TABLE_B)

기존에 TABLE_B의 값이 동적으로 변경되어 위와 같이 데이터를 조회해야 했습니다.

 

하지만 TABLE_A의 데이터가 변경되어 위의 쿼리는 쓸수 없게 되었습니다.

같은 결과를 얻기 위해 하기와 같이 변형하였습니다.

SELECT * 
  FROM TABLE_A 
 WHERE LEFT( COL_A,3 ) IN ( SELECT COL_B FROM TABLE_B )

이렇게 되자 인덱스가 타지 않으면서 엄청나게 속도가 느려졌습니다.

 

TABLE_A의 데이터는 100만건 정도되고

TABLE_B의 값은 50건정도 입니다.

두 테이블 다 값이 유동적입니다.

 

 

WHERE COL_A IN ('A%', 'B%', 'C%') 같이 조회하고 싶지만...

구글링을 해봐도 실제로 방법은 없는 것 같고..

혹시 좋은 방법이 있을까 싶어 이렇게 질문드리게 되었습니다.

 

참고로 ORACLE에서만 쓰는 함수가 있어도... 쓰면 안됩니다. ㅠㅠ

 

만약 쿼리로 해결을 볼 수 없다면 서버 단에서 

DYNAMIC QUERY로 LIKE OR LIKE OR ... OR LIKE  50개 로 만들어서 맵핑하려고 생각중입니다.

 

애타게 답변 기다립니다. 

읽어주셔서 감사합니다.

 

by 아발란체 [2016.08.05 01:04:00]

아무튼 최종 조회 건수가 50건인데.. 느리다면, 쿼리보다 테이블 구조 정규화가 문제가 아닌가 찍어봅니다. ㅋㅋ

느려진 문제는 "LEFT( COL_A,3 ) IN " 요게 문제입니다.

인덱스 항목을 가공하면, 인덱스를 타지 않습니다.

다이나믹보다, 이 방법으로 풀이하시는 것이 좋을 것 같습니다.

 

인덱스 항목만 빠르게 조회, 중복 제거 가공하고, 가공한 값으로 등치 조건을 걸 수 있겠으나,

변경된 A테이블 데이타 변경이 아닌 컬럼을 추가하여 - 뒤 값을 따로 저장하는 것이 바람직한 것이 아닌가 생각합니다. 데이타가 많아질 수록 비용이 점점 증가 할 것 같습니다.


by jkson [2016.08.05 08:04:22]

쿼리로 해결하시기보다 아발란체님 말씀대로 컬럼을 하나 더 추가하시는 게 장기적으로 봤을 때 좋을 것 같네요. B테이블이 코드성 테이블이다 보니 해당 쿼리 이외에서도 A테이블과 B테이블을 조인했을 가능성도 있을 것 같구요. 함수나 쿼리로 해결한다 하더라도 추후 개발하는 모든 쿼리에서 쉽지 않은 방법으로 개발해야 할 것이구요.


by 마농 [2016.08.05 08:51:56]
-- 서브쿼리보다는 조인이 나을 듯 하네요.
-- 조인은 두가지 방향으로 가능합니다.
SELECT a.*
  FROM table_a a
 INNER JOIN table_b b
    ON LEFT(a.col_a, 3) = b.col_b
;
SELECT a.*
  FROM table_a a
 INNER JOIN table_b b
    ON a.col_a LIKE CONCAT(b.col_b, '%')
;

 


by 네오스타 [2016.08.05 08:54:21]
아발란체님, jkson님 답변 감사합니다.
이번에 외부에서 받는 데이터가 저렇게 바뀐것입니다.
TABLE_A의 COL_A 이외에 다른 1개의 컬럼도 저런식으로 바뀌었습니다. 앞으로 어떻게 또 들어올지 몰라 추이를 보고 말씀하신 부분 참고하겠습니다.

일단 쿼리로는 힘들어보인다니 고민을 더 해봐야겠습니다.

by 네오스타 [2016.08.05 09:32:05]
마농님 답변 감사합니다.

같은 방법으로도
속도는 여전히 느리네요.
컬럼을 조작해서 연산을 하는것 자체가 비용을
너무 잡아먹는것 같습니다.

by 마농 [2016.08.05 09:39:28]

위와 같이 조인을 하면.
컬럼 조작은 한쪽에서만 이루어 지므로 조작되지 않은 반대쪽 인덱스는 이용이 가능합니다.
최종 조회 건수가 어떻게 되나요?
쿼리 일부만 올리신 듯 한데요? 전체 쿼리는 어떻게 되나요?


by 네오스타 [2016.08.05 10:23:15]
마농님 말씀이 맞습니다
최종 조회건수는 평균 30건 최대 60건정도 입니다
쿼리는 일부만 올렸습니다 ( 죄송합니다 ㅠ )

현재 진행상황은 A테이블을 group by로 뽑아( 대략 3000건 ) A컬럼을 조작한 컬럼을 B 테이블과 exists로 존재여부만 파악하는 식으로 짰더니 예전 속도와 비슷해졌습니다.

다시한번 시간 내서 소중한 조언해주셔서 감사드립니다.

by 마농 [2016.08.05 10:27:51]

A 100만건을 그룹바이 하여 3000 으로 만들고 b 와 조인하신 듯 하네요?
만약 그러하다면?
B 를 풀스캔하면서 Exists 서브쿼리로 A 의 존재여부만 파악하면 더 좋지 않을까 생각되네요.
전체 쿼리를 보지 못해 확실하지는 않습니다만...


by 네오스타 [2016.08.05 11:16:21]
마농님 또 소중한 답변 감사합니다

PC로 게시글을 올릴 수 없는 상황이라
모바일로 쓰고 있습니다.

풀쿼리는 A테이블에 A컬럼만 있는 것이 아니라
조금더 말씀드리면
A, A-1,금액 컬럼 이렇게 3개가 있습니다.
이렇게 추출한 데이터를 WITH_A 라고 한다면
WITH_A A1
FULL OUTER JOIN WITH_A A2
ON A1.A = A2.A-1
AND A2.A = A1.A-1

로 걸어서 비교하여 금액이 큰 ROW 만 추출하는게 목적이었습니다.

결론은 로우 단위로
A B 100원
B A 10원

하기와 같이 존재한다면
A B 100원만
추출하려고 하였습니다!

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