쿼리 간소화 관련 조언 부탁드립니다. 0 2 4,825

by 새싹 [SQL Query] [2024.02.02 21:24:55]


안녕하세요. 이번 한주도 고생 많으셨습니다 ㅎㅎ

원하는 방향으로 로직을 구현하긴 했는데, 조금 로직을 단순화 할 수 있는 방향을 생각해보다가 문의드리게 되었습니다.

기준일 (1/15) 기준으로 1/12 ~ 1/14 일 구간의  (요구합계 - 적용합계) 를 기준일 이후로 요구가 있는 가장 빠른 날에 더해주는 로직 입니다.

 

샘플 테이블의 T1 = 요구 테이블,  T2 = 적용 테이블 입니다.

로직을 짜긴 짰는데.. 짜다보니 요구 테이블을 모수로 3번이나 활용하였습니다... 

1.  ( 요구 - 수량 ) 구할 때,

2.  1에서 구한 수량, 구간 이후 수량있는일자에 더해주고, 가장 최근 일자만 발췌. 

3.  NVL(요구테이블수량, 2에서 구한 가장최근일자 수량)

 

뭔가 동일한 테이블 3번쓴게 찝찝한데 뭔가 해결을 못하고있어서 문의드려봅니다.. 

 

베이스 데이터

GROUP1 TYPE 1월 12일 1월 13일 1월 14일 1월 15일 1월 16일 1월 17일 1월 18일 1월 19일 1월 20일 1월 21일 1월 22일 1월 23일
A 요구 100 100 100 100 100 100            
A 적용                        
B 요구 100 100           100       100
B 적용                        

 

요구 수량 적용

          기준일                
GROUP1 TYPE 1월 12일 1월 13일 1월 14일 1월 15일 1월 16일 1월 17일 1월 18일 1월 19일 1월 20일 1월 21일 1월 22일 1월 23일
A 요구 100 100 100   365 100            
A 적용 5 20 10                  
B 요구 100 100           290       100
B 적용 5 5                    

 

WITH T1 AS ( 
SELECT 'A' AS GROUP1, TO_DATE('20240112','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'A' AS GROUP1, TO_DATE('20240113','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'A' AS GROUP1, TO_DATE('20240114','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL
SELECT 'A' AS GROUP1, TO_DATE('20240116','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'A' AS GROUP1, TO_DATE('20240117','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL  
SELECT 'B' AS GROUP1, TO_DATE('20240112','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'B' AS GROUP1, TO_DATE('20240113','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'B' AS GROUP1, TO_DATE('20240119','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
UNION ALL 
SELECT 'B' AS GROUP1, TO_DATE('20240123','YYYYMMDD') AS PLANDATE, 100 수량 FROM DUAL
  ),
T2 AS (
SELECT 'A' AS GROUP1, TO_DATE('20240112','YYYYMMDD') AS RESULTDATE, 5 수량 FROM DUAL
UNION ALL 
SELECT 'A' AS GROUP1, TO_DATE('20240113','YYYYMMDD') AS RESULTDATE, 20 수량 FROM DUAL
UNION ALL 
SELECT 'A' AS GROUP1, TO_DATE('20240114','YYYYMMDD') AS RESULTDATE, 10 수량 FROM DUAL
UNION ALL 
SELECT 'B' AS GROUP1, TO_DATE('20240112','YYYYMMDD') AS RESULTDATE, 5 수량 FROM DUAL
UNION ALL 
SELECT 'B' AS GROUP1, TO_DATE('20240113','YYYYMMDD') AS RESULTDATE, 5 수량 FROM DUAL
)
SELECT A.GROUP1, A.PLANDATE, NVL(B.요구SUM, A.요구)  AS QTY
  FROM (
        SELECT GROUP1, PLANDATE, 수량 as 요구
          FROM T1
         WHERE PLANDATE BETWEEN TO_DATE('20240112','YYYYMMDD') AND TO_DATE('20240125','YYYYMMDD')
       ) A,
       (
        SELECT A.GROUP1, A.PLANDATE, 요구SUM
          FROM (
                SELECT A.GROUP1, A.PLANDATE, A.요구 AS 요구, B.적용, B.부족, (A.요구+B.부족) AS 요구SUM,
                       ROW_NUMBER() OVER(PARTITION BY A.GROUP1 ORDER BY PLANDATE) RNK
                  FROM (
                        SELECT GROUP1, PLANDATE, 수량 AS 요구
                          FROM T1
                         WHERE PLANDATE BETWEEN TO_DATE('20240112','YYYYMMDD') AND TO_DATE('20240125','YYYYMMDD')
                           AND PLANDATE > TO_DATE('20240114','YYYYMMDD')
                       ) A,
                       (
                        SELECT A.GROUP1 AS GROUP1, A.요구 , B.적용 ,  (A.요구 - B.적용)  AS 부족
                          FROM (
                                SELECT GROUP1, SUM(수량) AS 요구
                                  FROM T1
                                 WHERE PLANDATE BETWEEN TO_DATE('20240112','YYYYMMDD') AND TO_DATE('20240114','YYYYMMDD')
                                 GROUP BY GROUP1
                               ) A,
                               (
                                SELECT GROUP1, SUM(수량) AS 적용
                                  FROM T2
                                 WHERE RESULTDATE BETWEEN TO_DATE('20240112','YYYYMMDD') AND TO_DATE('20240114','YYYYMMDD')
                                 GROUP BY GROUP1
                               ) B
                         WHERE A.GROUP1 = B.GROUP1(+)
                           AND A.요구 > B.적용
                       ) B
                 WHERE A.GROUP1 = B.GROUP1(+)
               ) A
         WHERE RNK = 1
      ) B
 WHERE A.GROUP1 = B.GROUP1(+)
   AND A.PLANDATE = B.PLANDATE(+)
 ORDER BY A.GROUP1, A.PLANDATE ASC;

GROUP DATE    수량

A    24/01/12    100
A    24/01/13    100
A    24/01/14    100
A    24/01/16    365
A    24/01/17    100
B    24/01/12    100
B    24/01/13    100
B    24/01/19    290
B    24/01/23    100

by 뉴비디비 [2024.02.02 23:20:34]
SELECT
    GROUP1, TO_CHAR(PLANDATE, 'YYYY-MM-DD') AS 날짜
    , CASE
        WHEN RN = 1 THEN
            ( sum(CASE WHEN PLANDATE < '2024-01-15' then 요구 ELSE 0 END ) over(PARTITION BY GROUP1) ) + 요구 - ( sum(적용) over(PARTITION BY GROUP1) )
        ELSE 요구 
      END AS 수량
FROM (
    SELECT
        T1.GROUP1, T1.PLANDATE, T1.수량 AS 요구, T2.RESULTDATE, T2.수량 AS 적용 , TRN.rn
    FROM T1
    LEFT JOIN T2 
        ON T1.GROUP1 = T2.GROUP1 AND T1.PLANDATE = T2.RESULTDATE
    LEFT JOIN(
        SELECT
            T1.PLANDATE , ROW_NUMBER() over(PARTITION BY GROUP1 ORDER BY PLANDATE) rn 
        FROM T1
        WHERE PLANDATE > '2024-01-15'
    ) TRN ON TRN.rn = 1 AND TRN.PLANDATE = T1.PLANDATE
) tbl
WHERE PLANDATE <> '2024-01-15'  -- 베이스데이터 표에는 15일 값이 있어서 결과에 제외 조건 추가 
ORDER BY GROUP1, PLANDATE

 


by 마농 [2024.02.04 23:06:30]
WITH t1 AS
(
SELECT 'A' group1, TO_DATE('20240112', 'yyyymmdd') plandate, 100 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240113', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240114', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240116', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240117', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240112', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240113', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240119', 'yyyymmdd'), 100 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240123', 'yyyymmdd'), 100 수량 FROM dual
)
, t2 AS 
(
SELECT 'A' group1, TO_DATE('20240112', 'yyyymmdd') resultdate, 5 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240113', 'yyyymmdd'), 20 수량 FROM dual
UNION ALL SELECT 'A', TO_DATE('20240114', 'yyyymmdd'), 10 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240112', 'yyyymmdd'),  5 수량 FROM dual
UNION ALL SELECT 'B', TO_DATE('20240113', 'yyyymmdd'),  5 수량 FROM dual
)
SELECT a.group1
     , a.plandate
     , DECODE(a.plandate, a.일자, a.요구 - NVL(b.적용, 0), a.수량) qty
  FROM (SELECT group1
             , plandate
             , 수량
             , MIN(CASE WHEN plandate > TO_DATE('20240114', 'yyyymmdd')
                        THEN plandate END) OVER(PARTITION BY group1) 일자
             , SUM(수량) OVER(PARTITION BY group1 ORDER BY plandate) 요구
          FROM t1
         WHERE plandate >= TO_DATE('20240112', 'yyyymmdd')
           AND plandate <= TO_DATE('20240125', 'yyyymmdd')
        ) a
     , (SELECT group1
             , SUM(수량) 적용
          FROM t2
         WHERE resultdate >= TO_DATE('20240112', 'yyyymmdd')
           AND resultdate <= TO_DATE('20240114', 'yyyymmdd')
         GROUP BY group1
        ) b
 WHERE a.group1 = b.group1(+)
 ORDER BY a.group1, a.plandate
;

 

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