조건에 따라 update 를 하는 프로시저를 만드는데요 0 7 1,887

by 이프로부족 [SQL Query] [2012.10.22 10:57:33]



안녕하세요. 업무중에 쉬운 쿼리인데 쿼리를 짜본적이 거의 없어서

막히고 있습니다.. ㅠㅠ 고수님들 좀 도와주세요.

다음의 테이블이 있는데요

posnum 수량
0 19
1 20
2 20
3 15
4 5

수량에 들어가는 최대값은 20 입니다.

여기서 10 개의 새 수량을 빈 공간 (0, 3,4)에 비어있는지 확인해서 0 번부터 채워넣어야 하는데요.

즉 여기서 0번에 1개를 더하고

3번에 5개를 더하고

4번에 10개중 0번과 3번에 넣은 6개를 제외한 나머지 4개를 넣어서

posnum 수량
0 20
1 20
2 20
3 20
4 9

이런식으로 업데이트 하는 프로시저를 짜야하는데

도저히 뭐부터 시작해야 할지 답이 안나오네요.. ㅠㅠ 좀 도와주세요

by 부쉬맨 [2012.10.22 11:09:44]
select 20 -
case when 수량  > 10 then 20 else 10 end 수량 into  수량
from 테이블


일단이렇게짜는데
4번은10이하의 데이터는 무조건저렇게되야되는건지

먼가 기준이 모호함..

글로적힌대로한다면 0,3 의 값을 담아서 처리하시면되겠네요.

by 부쉬맨 [2012.10.22 11:14:43]
  select 20 - 
case when 수량  > 10 then 수량 end 나머지수량
from 테이블

update 
 set 수량 = 수량 + 
나머지수량

나머지수량의합 := 나머지수량의합 +
나머지수량

마지막에 10 이하의 자료에 대해서 

update 
 set 수량 = 수량 + 나머지수량의합
where 수량 < 10

두서는 없지만 절차적으로 일단 20의데이터에 대해서 수정후 
그값을 더한거에 대한 결과값을 마지막에 처리하는방식을 취해야될뜻..

by 필상 [2012.10.22 11:38:42]

WITH TMP AS(
SELECT 0 AS GUBUN, 19 AS CNT FROM DUAL UNION ALL
SELECT 1 AS GUBUN, 20 AS CNT FROM DUAL  UNION ALL
SELECT 2 AS GUBUN, 20 AS CNT FROM DUAL  UNION ALL
SELECT 3 AS GUBUN, 15 AS CNT FROM DUAL  UNION ALL
SELECT 4 AS GUBUN, 5 AS CNT FROM DUAL  UNION ALL
SELECT 5 AS GUBUN, 19 AS CNT FROM DUAL )
SELECT GUBUN, CNT,
   CASE WHEN SUM(BASE_CNT - CNT) OVER(ORDER BY GUBUN) < INPUT_CNT THEN BASE_CNT ELSE
    CASE WHEN SUM(BASE_CNT - CNT) OVER(ORDER BY GUBUN ROWS UNBOUNDED PRECEDING) - (BASE_CNT - CNT) < INPUT_CNT THEN
INPUT_CNT - (SUM(BASE_CNT - CNT) OVER(ORDER BY GUBUN ROWS UNBOUNDED PRECEDING) - (BASE_CNT - CNT)) + CNT
    ELSE CNT END
   END
  FROM TMP,
   ( SELECT 20 AS BASE_CNT, 10 AS INPUT_CNT FROM DUAL);

by 마농 [2012.10.22 11:42:28]
CREATE OR REPLACE PROCEDURE p_update(v_cnt NUMBER)
IS
    CURSOR c1 IS
    SELECT posnum, cnt
      FROM t
     WHERE cnt < 20
     ORDER BY posnum
    ;
    v_in_cnt NUMBER(2) := v_cnt;
    v_up_cnt NUMBER(2);
    user_define_error EXCEPTION;
BEGIN
    FOR c IN c1 LOOP
        IF c.cnt + v_in_cnt > 20 THEN
            v_up_cnt := 20 - c.cnt;
        ELSE
            v_up_cnt := v_in_cnt;
        END IF;
        UPDATE t
           SET cnt = cnt + v_up_cnt
         WHERE posnum = c.posnum
        ;
        v_in_cnt := v_in_cnt - v_up_cnt;
        EXIT WHEN v_in_cnt <= 0;
    END LOOP;
    -- 입력값이 남는 경우 두가지 처리방법 소개 --
    -- CASE 1. 사용자 에러 발생 --
    -- IF v_in_cnt > 0 THEN
    --     RAISE user_define_error;
    -- END IF;
    -- CASE 2. 신규 데이터 생성 --
    -- WHILE v_in_cnt > 0 LOOP
    --     IF v_in_cnt > 20 THEN
    --         v_up_cnt := 20;
    --     ELSE
    --         v_up_cnt := v_in_cnt;
    --     END IF;
    --     INSERT INTO t
    --     SELECT NVL(MAX(posnum), 0) + 1
    --          , v_up_cnt
    --       FROM t
    --     ;
    -- END LOOP;
    -- COMMIT;
EXCEPTION
    WHEN user_define_error THEN
        RAISE_APPLICATION_ERROR(-20001, '빈공간에 비해 입력수량이 너무 많습니다.');
END;
/

by 이프로부족 [2012.10.22 11:49:04]

감사합니다. 달아주신 댓글을 토대로 연구를 좀 해보겠습니다.

by 마농 [2012.10.22 12:16:52]

insert 후에 다음 한줄이 빠졌네요. 참고하세요.
v_in_cnt := v_in_cnt - v_up_cnt;


by 장비 [2012.10.24 14:56:30]
UPDATE TB Y
  SET Y.수량 = (SELECT A.수량+ DECODE( GREATEST(S,0) , 0, GREATEST(B+S, 0), B)
              FROM (
                  SELECT T.posnum
                     , T.수량
                     , 20- T.수량 AS B
                     , 10 -SUM(20- T.수량) OVER ( ORDER BY posnum ) AS S
                   FROM TB T
               )A
               WHERE A.posnum = Y.posnum 
            )
 WHERE Y.posnum IN ( '0','1','2','3','4')
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입