case when & 서브 쿼리 성능 관련 질문 (절실!!!) 0 6 5,564

by 바카니 [SQL Query] postgresql query db [2020.04.23 11:01:05]


캡처.JPG (80,581Bytes)

안녕하세요. 답변 주신다면 정말 감사하겠습니다.

 

* 질문 1. 아래 현재 쿼리에서 서브쿼리 이용해서 case 문으로 감싸서 가져오고 있는 쿼리 방식의 속도 개선을 위해 어떻게 바꿀 수 있을까요?

(덧붙임 내용 :

각 where 조건의 값에 맞춰서 값을 가져오고 있는데, 조건이 건수를 이용해서 값을 판별하여 case 문을 주는거라

일단 이렇게는 짜놨는데...속도가 문제네요. )

 

* 현재 쿼리

select
            <foreach collection="time" item="item" separator=",">
                case
                when (select count(1) from tb_test_result2 where use_yn = 'Y' and line_no = #{line_no} and prod_sapcode = #{prod_sapcode} and to_char(test_date, 'yyyymmddhh24') = to_char(now(), 'yyyymmdd')||#{item.cd_id})<![CDATA[<]]>10 or #{item.cd_id}<![CDATA[>]]>to_char(now(), 'hh24') then 'F'
                when (select count(1) from tb_error_act_ht where use_yn = 'Y' and act_finish_yn = 'N' and to_char(error_sdate, 'yyyymmddhh24') = to_char(now(), 'yyyymmdd')||#{item.cd_id} and line_no = #{line_no} and prod_sapcode = #{prod_sapcode})<![CDATA[>]]>1 then 'RR'
                when (select count(1) from tb_error_act_ht where use_yn = 'Y' and act_finish_yn = 'N' and to_char(error_sdate, 'yyyymmddhh24') = to_char(now(), 'yyyymmdd')||#{item.cd_id} and line_no = #{line_no} and prod_sapcode = #{prod_sapcode})<![CDATA[>]]>0 then 'R'
                when (select count(1) from tb_error_act_ht where use_yn = 'Y' and act_finish_yn = 'Y' and to_char(error_sdate, 'yyyymmddhh24') = to_char(now(), 'yyyymmdd')||#{item.cd_id} and line_no = #{line_no} and prod_sapcode = #{prod_sapcode})<![CDATA[>]]>0 then 'C'
                when (select count(1) from tb_test_result2 where use_yn = 'Y' and line_no = #{line_no} and prod_sapcode = #{prod_sapcode} and to_char(test_date, 'yyyymmddhh24') = to_char(now(), 'yyyymmdd')||#{item.cd_id})<![CDATA[>]]>10 and #{item.cd_id}||'00'<![CDATA[<=]]>to_char(now(), 'hh2400') and #{item.cd_id}||'59'<![CDATA[>=]]>to_char(now(), 'hh2400') then 'GG'
                else 'G' end as h${item.cd_id}
            </foreach>

 

가독성을 위해 이미지도 첨부하겠습니다!!!

by 마농 [2020.04.23 13:57:56]

시간이 '09' 시만 조회하나요?
아니면 이런 쿼리가 반복되나요?
몇시부터 몇시까지 반복하면 되는 건가요? 고정인가요? 가변인가요?


by 바카니 [2020.04.23 15:20:37]

이런 쿼리가 for each로 반복됩니다!

가변입니다! 몇시부터 몇시까지인지는 parameter 값으로 주고 있습니다. 현재값 기준으로는 09시부터 21시까지 입니다.


by 마농 [2020.04.23 15:30:39]

현재 작성된 쿼리의 조건에는 문제가 없는 건가요?
OR 조건도 들어가고? 테이블도 2개네요?
각각의 조건이 서로 겹치지 않는 조건이면 모르겠는데.
조건이 겹치는 경우가 발생된다면?
조건의 우선순위가 중요한데요.
조건의 배치 순서에 따라 결과가 달라질 수 있습니다.
조건은 우선순위 대로 배치된 건 맞겠죠?
테이블이 2개인데 처음과 마지막이 같은 테이블이고 중간에 다른 테이블이 들어가네요?
조건이 이렇게 배치되는 게 맞는 건지?


by 바카니 [2020.04.23 15:35:02]

넵. 해당 조건은 우선순위 대로 배치되었습니다!
2개의 테이블인데, 해당 값이 있을 경우에 대한 순서대로 걸러집니다. 화면에서 보여주기 위함입니다.

해당 쿼리에 대해서 다르게 짜 볼 수 있는 방식이 있는지 궁금해서 남겼습니다.^^


by 마농 [2020.04.23 16:23:27]
SELECT MIN(CASE h WHEN  9 THEN v END) h09
     , MIN(CASE h WHEN 10 THEN v END) h10
     , MIN(CASE h WHEN 11 THEN v END) h11
     , MIN(CASE h WHEN 12 THEN v END) h12
     , MIN(CASE h WHEN 13 THEN v END) h13
     , MIN(CASE h WHEN 14 THEN v END) h14
     , MIN(CASE h WHEN 15 THEN v END) h15
     , MIN(CASE h WHEN 16 THEN v END) h16
     , MIN(CASE h WHEN 17 THEN v END) h17
     , MIN(CASE h WHEN 18 THEN v END) h18
     , MIN(CASE h WHEN 19 THEN v END) h19
     , MIN(CASE h WHEN 20 THEN v END) h20
     , MIN(CASE h WHEN 21 THEN v END) h21
  FROM (SELECT h.h
             , CASE WHEN h.h > DATE_PART('hour', now()) THEN 'F'
                    WHEN COALESCE(a.cnt_1, 0) < 10      THEN 'F'
                    WHEN COALESCE(b.cnt_n, 0) >  1      THEN 'RR'
                    WHEN COALESCE(b.cnt_n, 0) >  0      THEN 'R'
                    WHEN COALESCE(b.cnt_y, 0) >  0      THEN 'C'
                    WHEN COALESCE(a.cnt_1, 0) > 10
                     AND h.h = DATE_PART('hour', now()) THEN 'GG'
                    ELSE 'G' END v
          FROM generate_series(9, 21) h(h)
          LEFT OUTER JOIN
               (SELECT DATE_PART('hour', test_date) h
                     , COUNT(*) cnt_1
                  FROM tb_test_result2
                 WHERE use_yn = 'Y'
                   AND line_no = #{line_no}
                   AND prod_sapcode = #{prod_sapcode}
--                 AND TO_CHAR(test_date, 'yyyymmdd') = TO_CHAR(NOW(), 'yyyymmdd')
                   AND test_date >= DATE_TRUNC('day', NOW())
                   AND test_date <  DATE_TRUNC('day', NOW() + INTERVAL '1 day')
                 GROUP BY DATE_PART('hour', test_date)
                ) a
            ON h.h = a.h
          LEFT OUTER JOIN
               (SELECT DATE_PART('hour', error_sdate) h
                     , COUNT(CASE WHEN act_finish_yn = 'N' THEN 1 END) cnt_n
                     , COUNT(CASE WHEN act_finish_yn = 'Y' THEN 1 END) cnt_y
                  FROM tb_error_act_ht
                 WHERE use_yn = 'Y'
                   AND line_no = #{line_no}
                   AND prod_sapcode = #{prod_sapcode}
--                 AND TO_CHAR(error_sdate, 'yyyymmdd') = TO_CHAR(NOW(), 'yyyymmdd')
                   AND error_sdate >= DATE_TRUNC('day', NOW())
                   AND error_sdate <  DATE_TRUNC('day', NOW() + INTERVAL '1 day')
                 GROUP BY DATE_PART('hour', error_sdate)
                ) b
            ON h.h = b.h
        ) c
;

 


by 바카니 [2020.05.15 16:21:36]

와 답변이 늦어 죄송합니다!!!
속도가 훨씬 개선되었어요. ㅠㅠ 절드리고 싶을만큼 감사합니다ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ

어떻게 그렇게 잘 짜실 수 있는지요...

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