쿼리 튜닝 관련 질문 입니다. 0 7 1,355

by 후레쉬 [SQL Query] [2014.07.14 19:03:33]


WITH T AS ( 
SELECT '서울' AS kind, '딸기' AS nm, 3000 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '사과' AS nm, 2000 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '참외' AS nm, 2500 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '딸기' AS nm, 2300 AS price FROM DUAL UNION ALL 
SELECT '부산' AS kind, '참외' AS nm, 1800 AS price FROM DUAL UNION ALL 
SELECT '대구' AS kind, '사과' AS nm, 3200 AS price FROM DUAL

SELECT 
kind,nm,
COUNT(*)/(SELECT COUNT(*) FROM T WHERE kind = '서울' AND nm = T.nm) * 100 AS PER
FROM T 
WHERE kind = '서울'
GROUP BY kind, nm;

 

 

 

위와 같은 쿼리가 있습니다. 노랑 바탕색 부분인데요,,, WHERE kind = '서울' 로 걸러낸 결과물중에서 딸기, 참외, 사과가 각각 전체 카운트 중에 몇% 인가인데요...

물론, 결과물은 맞습니다. 근데, 제가 궁금한건, 이미 WHERE kind = '서울' 이미 여기서 한번 걸러냈는데, 

또, (SELECT COUNT(*) FROM T WHERE kind = '서울' AND nm = T.nm)  이렇게 동일하게 걸러내야 하냐는 겁니다.

이 보다 더 빠르고, 유용한 쿼리가 있나요?

 

답변 부탁 드립니다 (__)

by 우리집아찌 [2014.07.14 20:22:50]

http://www.gurubee.net/lecture/2675

RATIO_TO_REPORT  쓰시면 될듯한데요..


by 마농 [2014.07.15 08:30:49]
-- 작성하신 쿼리는 결과는 맞게 나오는지 모르겟지만...
-- 서브쿼리의 조건 (nm = T.nm) 은 결국 1=1 과 같은 조건입니다.
-- t.nm 은 메인의 항목이 아니라 서브의 항목입니다.
-- 즉 없어도 될 조건이며, 결국은 서울의 건수를 구하는 서브쿼리인거죠.
-- 서브쿼리 조건은 상수보다는 메인쿼리의 항목으로 주는것이 좋을 듯 하구요
-- 분석함수를 이용한다면 서브쿼리 없이 구하실 수 있습니다.
SELECT kind,nm
     , COUNT(*) / (SELECT COUNT(*) FROM t WHERE kind = m.kind) * 100 per1
     , COUNT(*) / SUM(COUNT(*)) OVER(PARTITION BY kind) * 100 per2
     , RATIO_TO_REPORT(COUNT(*)) OVER(PARTITION BY kind) * 100 per3
  FROM t m
 WHERE kind = '서울'
 GROUP BY kind, nm
;

 


by 후레쉬 [2014.07.15 12:30:34]

마농님 답변 감사드립니다.

추가 질문 드릴께요... 만일 where 절에 추가가 될 경우, per2 나 per3 의 함수에도 가능한가요?

예를들면, 

COUNT(*) / (SELECT COUNT(*) FROM t WHERE kind = m.kind and price > 2000) * 100 per1

이렇게...  and price > 2000 이게 추가가 되었습니다.

per2 나 per3 에도 반영이 가능할까요?


by 마농 [2014.07.15 13:13:16]

해당 조건이 전체 조건인지 부분 조건인지에 따라 다릅니다.

전체 적용되어야 하는 조건이라면? Where 절에만 추가하면 끝이죠.

부분적으로 적용되어야 하는 조건이라면? Case 문을 이용해야죠.

COUNT(CASE WHEN price > 2000 THEN 1 END)

아마도 부분조건은 아닌듯 싶네요?


by 후레쉬 [2014.07.15 17:48:14]

답변 감사드립니다 ^^;
아 근데,,,


WITH T AS ( 
SELECT '서울' AS kind, '딸기' AS nm, 3000 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '사과' AS nm, 2000 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '참외' AS nm, 2500 AS price FROM DUAL UNION ALL 
SELECT '서울' AS kind, '딸기' AS nm, 2300 AS price FROM DUAL UNION ALL 
SELECT '부산' AS kind, '참외' AS nm, 1800 AS price FROM DUAL UNION ALL 
SELECT '부산' AS kind, '딸기' AS nm, 2800 AS price FROM DUAL UNION ALL 
SELECT '대구' AS kind, '사과' AS nm, 3200 AS price FROM DUAL

SELECT kind,nm
     , COUNT(*) / (SELECT COUNT(*) FROM t WHERE kind = m.kind) * 100 per1
     , COUNT(*) / SUM(COUNT(*)) OVER(PARTITION BY kind) * 100 per2
     , COUNT(case when price > 2000 then price end) / SUM(COUNT(*)) OVER(PARTITION BY kind) * 100 per2   => 이건 되는데,,,
     , RATIO_TO_REPORT(COUNT(*)) OVER(PARTITION BY kind) * 100 per3
     , RATIO_TO_REPORT(COUNT(*)) OVER(PARTITION BY case when price > 2000 then kind end) * 100 per3  => 이건 에러 나네요..
FROM t m
WHERE kind = '서울'
GROUP BY kind, nm;


price 는 group by 표현식이 아닙니다.

이러한 식으로는 사용이 안되나 보네요;;


by 마농 [2014.07.15 23:37:41]
뭘 원하는건지 모호하긴 하지만...
방법은 동일합니다.
Count 안에서 Case 를 사용해야죠.
원하는 결과가 뭔지를 명확하게 알려주세요.
모호한 설명보다는...원본 대비 결과표를 보여주시는게 확실합니다.

by 후레쉬 [2014.07.16 10:22:40]

마농님 답변 감사 드립니다.

좋은 하루 되세요 ^^

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