이전 row를 이용한 계산 문의 0 6 1,287

by eddy [SQL Query] verticadb 수식계산 ABS [2022.10.19 10:01:31]


안녕하세요

쿼리에 대해 잘 몰라서 약 2주가량 구글링 해봐도 문제에 답을 찾지 못하여 여기에 문의 드립니다.

현재 업무에서 사용하는 DB는 verticadb 이고 oracle의 대부분의 쿼리가 동작합니다. 

다만 약간의 기능 차이와 connect by, pivot 등의 함수는 동작하지 않아 가능한 ansi표준으로 부탁드립니다.

[수식]

NO Q T V W
1 고정값 고정값 Q1 - W1 T1 * 01
2 고정값 T1 - V1 Q2 - W2 T2 * 0.1
3 고정값 T2 - V2 Q3 - W3 T3 * 0.1
4 고정값 T3 - V3 Q4 - W4 T4 * 0.1

* 고정값 : 특정 값이 들어 있습니다.

* T1 형식의 의미는 T열의 1 Row의 값을 의미합니다.

* W열은 소수점 무시하면 됩니다.

 

[데이터]

  Q T V W
1 100 200 80 20
2 100 120 88 12
3 100 32 97 3
         

와 같은 형식으로 계산됩니다.

 

대상은 총 60만건 이고 대상당 60개의 row가 계산으로 생성되어야 합니다. 

recursive를 이용하여 계산하는 쿼리를 작성했으나 verticadb는 recusive를 사용할때 최대 9개로 제한되어 있으며 제한을 60으로 변경하면 메모리 부족 오류가 발생됩니다.

첫번째 row와 2 ~ 60 row를  구할때 쿼리를 분리 해도 상관없습니다.

 

읽어 주셔서 감사합니다.

 

by 마농 [2022.10.19 13:48:26]
-- Oracle Recursive --
WITH t0 AS
(
SELECT 1 id, 100 q, 200 t FROM dual
UNION ALL SELECT 2, 200, 400 FROM dual
)
, t1(id, no, q, t, v, w) AS
(
SELECT id
     , 1 no
     , q
     , t
     , q - FLOOR(t * 0.1) v
     , FLOOR(t * 0.1) w
  FROM t0
 UNION ALL
SELECT id
     , no + 1 no
     , q
     , t - v t
     , q - FLOOR((t - v) * 0.1) v
     , FLOOR((t - v) * 0.1) w
  FROM t1
 WHERE no < 3  -- 60
)
SELECT *
  FROM t1
 ORDER BY id, no
;

 


by eddy [2022.10.19 14:00:18]

답변 감사합니다.

vertica에서 실행해보겠습니다.^^

 


by eddy [2022.10.19 15:14:47]

vertica db에서 실행 해보았습니다.

recursive 방식을 사용하신것 같아서 기본 설정으로 실행 했을때는 정상이였으나

(vertica db 는 WithClauseRecursionLimit parameter값이 9로 설정되 있습니다.)

 

설정과 조건을 60으로 변경 하고 실행 해보니 아래와 같은 오류가 발생되었습니다.

 

Total allocated memory (MiB) = 1024 is about to exceed limit imposed by MaxParsedQuerySizeMB (MiB) ... 

 

MaxParsedQuerySizeMB 설정 변경 요청을 해야 하는데 가능할지 걱정되네요.

다시한번 답변 감사합니다.

 


by 마농 [2022.10.19 18:01:25]
CREATE OR REPLACE FUNCTION f_test4
( v_n NUMBER
, v_q NUMBER
, v_t NUMBER
)
RETURN VARCHAR2
IS
    q NUMBER := v_q;
    t NUMBER := v_t;
    v NUMBER := 0;
    w NUMBER;
    v_rtn VARCHAR2(200);
BEGIN
    FOR n IN 1..v_n LOOP
        t := t - v;
        w := FLOOR(t * 0.1);
        v := q - w;
    END LOOP;
    v_rtn := t ||','|| v ||','|| w;
    RETURN v_rtn;
END;
/

WITH t0 AS
(
SELECT 1 id, 100 q, 200 t FROM dual
UNION ALL SELECT 2, 200, 400 FROM dual
)
, copy_t AS
(
SELECT LEVEL no FROM dual
 CONNECT BY LEVEL <= 4 --60
)
SELECT id
     , no
     , q
     , REGEXP_SUBSTR(x, '[^,]+', 1, 1) t
     , REGEXP_SUBSTR(x, '[^,]+', 1, 2) v
     , REGEXP_SUBSTR(x, '[^,]+', 1, 3) w
  FROM (SELECT id, no, q, t
             , f_test4(no, q, t) x
          FROM t0
             , copy_t
        ) a
 ORDER BY id, no
;

 


by eddy [2022.10.20 08:58:29]

담당자와 협의(?) 중에 새로운 해결책을 주셨네요..^^

정말 감사합니다.^^


by eddy [2022.10.24 14:41:17]

혹시 저와 비슷한 상황을 경우가 있을것 같아 함수로 테스트한 결과 댓글로 남깁니다. ^^

 

verticadb에서 function 사용시 FOR문을 사용할수 없고 단순히 계산 로직만 넣을수 있네요

(https://www.vertica.com/docs/9.3.x/HTML/Content/Authoring/SQLReferenceManual/Statements/CREATEFUNCTIONSQLFunctions.htm

http://vertica-forums.com/viewtopic.php?t=786)

 

마농님께서 좋은 해결책을 알려주셨는데 verticadb에서는 사용할수 없어  60번 쿼리를 실행하는 방식으로 했습니다. ^^;;;;

 

다시한번 마농님과 제글을 읽어주신분께 감사드립니다.

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