쿼리문 작성하는데 도움이 필요합니다. 0 7 1,222

by 박지영 [SQL Query] [2013.07.31 11:57:20]



자재 세팅 현황 작성을 위해 자재의 최초 입고일자 및 입고수량 뽑아야 되는데,
반품이 있을 경우 반품 후 최초 재입고 일자와 입고수량을 가져와야 쿼리입니다.
자재건수는 입고반품 합해서 대략 이만오천건정도 됩니다.
가령, 아래와 같은 경우
2013-07-15일자와 80이라는 수량을 가져와야 하는데
제 실력으로는 쿼리문이 쉽게 나오지가 않네요.
도움 부탁드립니다.

자재코드     구분 일자   수량
----------------------------------------------------------------------------------------
a    입고 2013-07-01 100
a     반품 2013-07-10 100
a    입고 2013-07-15    80
a         입고  2013-07-30    20

감사합니다.
by 마농 [2013.07.31 13:19:14]


반품한거를 제외한 최초 입고일자 뽑는거죠?


위 예시는 좀 심플한데요.
복잡하고 다양한 경우가 발생할 듯 한데요.


예1) 입고수량중 일부만 반품하는 경우 ==> 결과는? 7/1 50 ?
a 입고 2013-07-01 100
a 반품 2013-07-10  50
a 입고 2013-07-15  80
a 입고 2013-07-30  20


예2) 입고 2번 하고 난 후에 반품하는 경우 ==> 결과는? 7/2 80 ?
a 입고 2013-07-01 100
a 입고 2013-07-02  80
a 반품 2013-07-10 100
a 입고 2013-07-15  80
a 입고 2013-07-30  20


예3) 복잡한 경우 ==> 결과는? 7/2 80 ?
a 입고 2013-07-01 100
a 반품 2013-07-02  50
a 입고 2013-07-03  50
a 반품 2013-07-04  50 <== 이 반품은 과연
- 첫 입고에 대한 반품일지? 그렇다면 결과는? 7/3 50 ?
- 두번째 입고에 대한 반품일지? 이거라면 결과는 7/1 50 ?


by 박지영 [2013.07.31 14:09:24]

우선, 댓글 주신것에 너무 감사 드립니다. 답글을 기대하면서 계속 새로고침 하고 있었거든요

제가 예시를 너무 간단하게 했네요.
반품이 없는 경우에는 최초입고데이타를 가져와야 하고요, 반품이 있는 경우는 무조건 반품 이후 최초입고정보를 가져와야 합니다.

주신 예시의 결과값은,
예시1)의 경우 결과는 2013-07-15 / 80
예시2)의 경우 결과는 2013-07-15 / 80
예시3)의 경우는 입고일자 및 수량 없이 자재코드만 뿌려져야 됩니다.

TABLE     : MATIO
COLUMN : 자재코드(MATCD), 입고일자(MATDT), 입고수량(QTY), 입고구분(SECT : 100->입고, 200->반품)

SELECT T2.MATCD, T2.MATDT, T2.QTY
FROM   (SELECT  A.MATCD, MIN(A.MATDT) AS MINDT, (SELECT MAX(T1.MATDT) FROM  MATIO B
  WHERE  A.MATCD = B.MATCD
    AND  B.SECT    = '200') AS MAXDT
  FROM MATIO A
  WHERE  A.MATDT >= '20130601'
  AND    A.MATDT <= '20130731'
  AND    A.SECT = '100' ) T1,
  MATIO T2
WHERE   T2.MATCD  = T1.MATCD
AND     T2.MATDT >= '20130601'
AND     T2.MATDT <= '20130731'
AND     T2.SECT = '100'
AND     T2.MATDT  >= DECODE(T1.MAXDT, '', T1.MINDT, T1.MAXDT)
AND ROWNUM  = 1

여기까지 하곤 이게 맞는것인지 틀린것인지.. 더 좋은 쿼리는 없는지 고민하고 있습니다.

가르침 부탁드립니다.


by 타니 [2013.07.31 14:15:19]
저도 공부하는 입장이라 아래가 맞는지는 모르겠네요. 좀더 쉬운 방법이 있을 거라 생각합니다. 
일단 도움이 될 수 있을거라 생각해서 답변 남깁니다. 지금 환경이 SQL Server라 오라클 함수로는
테스트를 못해봤습니다.

WITH MATIO AS(
    SELECT 'a' MATCD, '100' SECT, '2013-07-01' MATDT, 100 QTY 
    UNION ALL 
    SELECT 'a' MATCD, '200' SECT, '2013-07-10' MATDT, 100 QTY 
    UNION ALL 
    SELECT 'a' MATCD, '100' SECT, '2013-07-15' MATDT, 80 QTY 
    UNION ALL 
    SELECT 'a' MATCD, '100' SECT, '2013-07-30' MATDT, 20 QTY 
)
select * from
(
    SELECT MATCD, SECT, MATDT, QTY
       ,RANK() OVER(ORDER BY MATDT ASC) RN 
    FROM MATIO    A
    WHERE MATDT    >= (SELECT MATDT FROM MATIO WHERE SECT = '200' AND MATCD = A.MATCD)
      AND SECT     = '100'
) T
WHERE RN = 1

by 박지영 [2013.07.31 14:31:47]
답변 주셔서 너무 감사합니다.
주신 쿼리를 참고하여 다시 해보도록 하겠습니다.

by 마농 [2013.07.31 15:14:58]
WITH matio AS
(
SELECT 'a' matcd, '100' sect, '2013-07-01' matdt, 100 qty FROM dual
UNION ALL SELECT 'a', '200', '2013-07-10',  50 FROM dual
UNION ALL SELECT 'a', '100', '2013-07-15',  80 FROM dual
UNION ALL SELECT 'a', '100', '2013-07-30',  20 FROM dual
UNION ALL SELECT 'b', '100', '2013-07-01', 100 FROM dual
UNION ALL SELECT 'b', '100', '2013-07-02',  80 FROM dual
UNION ALL SELECT 'b', '200', '2013-07-10', 100 FROM dual
UNION ALL SELECT 'b', '100', '2013-07-15',  80 FROM dual
UNION ALL SELECT 'b', '100', '2013-07-30',  20 FROM dual
UNION ALL SELECT 'c', '100', '2013-07-01', 100 FROM dual
UNION ALL SELECT 'c', '200', '2013-07-02',  50 FROM dual
UNION ALL SELECT 'c', '100', '2013-07-03',  50 FROM dual
UNION ALL SELECT 'c', '200', '2013-07-04',  50 FROM dual
UNION ALL SELECT 'd', '100', '2013-07-01', 100 FROM dual
UNION ALL SELECT 'd', '100', '2013-07-02',  50 FROM dual
)
SELECT matcd
     , MIN(DECODE(sect, 100, matdt)) matdt
     , MIN(DECODE(sect, 100, qty)) KEEP(DENSE_RANK FIRST ORDER BY sect, matdt) qty
  FROM (SELECT matcd, sect, matdt, qty
             , MAX(DECODE(sect, 200, matdt)) OVER(PARTITION BY matcd) maxdt
          FROM matio
        )
 WHERE matdt >= NVL(maxdt, '0001-01-01') -- c 도 나오게 하기 위해 등호(=) 포함
 GROUP BY matcd
;

by 박지영 [2013.07.31 16:25:49]

마농님 너무 감사드립니다^^
마농님 덕분에 머리아픈 숙제가 해결됐습니다.
그리고 이렇게도 할 수 있다는것을 오늘 배웠습니다.

감사드립니다.

by 손님 [2013.07.31 16:47:19]
WITH matio AS ( SELECT 'a' matcd, '100' sect, '2013-07-01' matdt, 100 qty FROM dual UNION ALL SELECT 'a', '200', '2013-07-10', 50 FROM dual UNION ALL SELECT 'a', '100', '2013-07-15', 80 FROM dual UNION ALL SELECT 'a', '100', '2013-07-30', 20 FROM dual UNION ALL SELECT 'b', '100', '2013-07-01', 100 FROM dual UNION ALL SELECT 'b', '100', '2013-07-02', 80 FROM dual UNION ALL SELECT 'b', '200', '2013-07-10', 100 FROM dual UNION ALL SELECT 'b', '100', '2013-07-15', 80 FROM dual UNION ALL SELECT 'b', '100', '2013-07-30', 20 FROM dual UNION ALL SELECT 'c', '100', '2013-07-01', 100 FROM dual UNION ALL SELECT 'c', '200', '2013-07-02', 50 FROM dual UNION ALL SELECT 'c', '100', '2013-07-03', 50 FROM dual UNION ALL SELECT 'c', '200', '2013-07-04', 50 FROM dual UNION ALL SELECT 'd', '100', '2013-07-01', 100 FROM dual UNION ALL SELECT 'd', '100', '2013-07-02', 50 FROM dual ) SELECT matcd , MIN(DECODE(sect, 100, matdt)) matdt , MIN(DECODE(sect, 100, qty)) KEEP(DENSE_RANK FIRST ORDER BY sect, matdt) qty FROM (SELECT matcd, sect, matdt, qty , MAX(DECODE(sect, 200, matdt)) OVER(PARTITION BY matcd) maxdt FROM matio ) WHERE matdt >= NVL(maxdt, '0001-01-01') -- c 도 나오게 하기 위해 등호(=) 포함 GROUP BY matcd ;
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입