안녕하세요. 쿼리추출에 관련하여 조언을 구하고자합니다.
SELECT
AA.sqx AS sqx,
AA.id AS id,
AA.passwd,
AA.name,
AA.comtype,
AA.comnametype,
AA.hphone,
AA.tphone,
AA.email,
AA.level,
AA.visit,
AA.wdate,
AA.c_end,
BB.*,
(
SELECT
comkkk
FROM
history
WHERE
uid=AA.id ORDER BY comkkk DESC limit 1
) AS comkkk
FROM
member AA
INNER JOIN company BB
ON AA.id = BB.id
LEFT OUTER JOIN memo CC
ON AA.id = CC.uid
WHERE AA.gubun = 'pp'
AND AA.id != '' GROUP BY AA.id ORDER BY AA.sqx desc
위와같은 쿼리문이 있는데요.
해당쿼리문에서 매출년도와 매출액을 입력하고 검색을하면 해당조건에 만족하는 리스트가 출력이 되는건데요.
디비컬럼을 보니 매출년도와 매출액의 컬럼이 하나로 되어있고 구성은 2000|2001|2002^1000|2000|3000
저런형태로 되어있는데요.
만약 2000년도 선택, 매출액 1000라고 입력하고 검색했을때 해당값을 추출할수있을까요?
조언좀 부탁드립니다.
RDBMS에서 빠질 수 없는 개념이 정규화인데요.
한 컬럼에는 되도록 하나의 정보만 저장한다는 게 정규화룰 중에 하나예요.
아마도 기존 테이블에 부가 정보를 기록해야 하는데 컬럼을 무한정 늘이기는 힘들고
그렇다고 테이블로 따로 빼자니 개발이 힘들 것 같고.. 그래서 저렇게 한 컬럼에 여러 정보를
입력한 게 아닌가 생각됩니다.
그런데 저런 식으로 입력해놓으면 호야별리님이 지금 경험하고 있는 검색의 어려움 문제가 필연적으로
발생할 수 밖에 없지요. 검색을 하려면 LIKE 구문을 쓰거나 데이터를 가공해야 하는데
데이터를 가공하는 것 자체도 성능을 떨어뜨리는데 가공된 결과에서 데이터를 찾아야 하니
인덱스 활용도 안 됩니다.
되도록 해당 정보를 별도의 테이블로 떼어내시고 원 테이블과 조인하여 활용하시는 게 좋을 것 같아요.
그런데 이미 프로그램이 저 컬럼 기준으로 많이 개발되어있다면 그렇게 하기 어렵겠지요..
그런데 지금 바꾸지 않으면 앞으로 더더욱 힘들어질 겁니다.
해당 데이터가 유의미한 정보로 자주 사용될 가능성이 높다면 테이블 따로 분리하세요.
원테이블이
기본키 + 다른 컬럼들 + 해당 컬럼
이런 구조라면 해당 컬럼의 정보를 가지고
(기본키 + 년도로 기본키 생성) + 매출액으로 구성된 새로운 테이블을 만드시구요.
원테이블의 해당 컬럼은 지워주시면 될 것 같습니다.
이렇게 만들면 검색시에도
select * from 원테이블 a where exists(select 1 from 신규테이블 b where b.기본키 = a.기본키 and b.년도 = '2000' and b.매출액 = 1000)
이렇게 해주시면 간단하겠죠.
SELECT a.sqx , a.id , a.passwd , a.name , a.comtype , a.comnametype , a.hphone , a.tphone , a.email , a.level , a.visit , a.wdate , a.c_end , b.* , (SELECT MAX(comkkk) FROM history WHERE uid = a.id) comkkk FROM member a INNER JOIN company a ON a.id = b.id INNER JOIN (SELECT DISTINCT uid , SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(memo, '^', 1), '|', lv), '|', -1) y , SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(memo, '^', -1), '|', lv), '|', -1) v FROM memo INNER JOIN (SELECT 1 lv UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ) copy_t ON lv <= (LENGTH(memo) - LENGTH(REPLACE(memo, '|', ''))) / 2 + 1 ) c ON a.id = c.uid WHERE a.gubun = 'pp' AND a.id != '' AND c.y = '2000' AND c.v = '1000' ORDER BY a.sqx DESC ;