구간 구하기 0 5 950

by 정충보국 [PL/SQL] [2017.09.28 09:40:47]


D컬럼의 순서가 안맞아서 order by D를 해서 pl/sql를 써서 다른 테이블에 A,B,C컬럼이 일치하면 update 그렇지 않으면 insert를 합니다.

이게 건수가 약 1,000만건 이나 되고 order by를 줘서 업데이트 시간이 너무 오래 걸리거나 무한루프가 돌아서 잘 안되네요.

updqte 시간이 덜 걸리는 방법이 없을까요?

A   B   C   D
A   01  1   1
B   01  1   3
A   01  1   2
B   01  1   5
C   02  2   4
B   01  1   7
C   02  2   9
B   01  1   6
A   01  1   10
C   02  2   8

----------------------------------------------------

결과값

A   B   C   min(D)   max(D)
A  01   1    1       2
B  01   2    3       3
C  02   2    4       4
B  01   1    5       7
C  02   2    8       9
A  01   1    10      10

by 마농 [2017.09.28 09:57:17]

결과와 설명이 일치하지 않네요?
a, b, c 컬럼이 일치하는 다른 테이블을 업데이트 하려면?
결과처럼 나와서는 안될 듯 한데요?
결과는 a, b, c 의 값이 중복되네요?
 - A 01 1 --> 2건
 - C 02 2 --> 2건


by 정충보국 [2017.09.28 09:59:33]

테이블의 값을 순차적으로 읽어서 결과값 테이블에 업데이트 하는거에요


by 마농 [2017.09.28 10:06:20]

결과값 테이블에 업데이트 한다는게 이상한데요?
min(d) 와 max(d) 를 업데이트 해야 할텐데요?
그럴려면 키를 a, b, c 를 사용하면?
중복이 되어서 안되고
a, b, c, min(d) 와 max(d) 까지를 키로 하면?
업데이트 한다는게 말이 안되구요. 키 이외에 업데이트할 컬럼이 없음.
이건 업데이트가 아니라
테이블 truncate 하고 새로 insert 하거나
테이블 drop 하고 CTAS 로 새로 만들어야 할 것 같네요.  --> 성능상 ctas 추천

 

만약 데이터 수정은 없이 insert 만 이루어지며
주기적으로 결과테이블에 업데이트 하는 거라면?
지난번 업데이트 처리한 d 값 이후의 자료만 가지고 업데이트 하는게 좋을 듯 하네요.
전체 천만건을 대상으로 를 하는 것보다 최근 것만 가지고 하는게 성능상 좋죠.
업데이트 키는 a, b, c, MIN(d) 로 해서 update 또는 insert 하는 merge 구문 이용하면 좋을 듯.


by 우리집아찌 [2017.09.28 09:58:26]
/* 다른테이블에 전부 넣으시고 테이블 RENAME 하심이 어떠실지 ./*/
WITH T ( A , B , C , D ) AS ( 
 SELECT 'A', '01' , 1 ,  1 FROM DUAL UNION ALL
 SELECT 'B', '01' , 1 ,  3 FROM DUAL UNION ALL
 SELECT 'A', '01' , 1 ,  2 FROM DUAL UNION ALL
 SELECT 'B', '01' , 1 ,  5 FROM DUAL UNION ALL
 SELECT 'C', '02' , 2 ,  4 FROM DUAL UNION ALL
 SELECT 'B', '01' , 1 ,  7 FROM DUAL UNION ALL
 SELECT 'C', '02' , 2 ,  9 FROM DUAL UNION ALL
 SELECT 'B', '01' , 1 ,  6 FROM DUAL UNION ALL
 SELECT 'A', '01' , 1 ,  10 FROM DUAL UNION ALL
 SELECT 'C', '02' , 2 ,  8 FROM DUAL
)
INSERT INTO TABLE 
SELECT A , B , C , MIN(D) , MAX(D)
  FROM (SELECT A , B, C , D 
             ,(ROW_NUMBER() OVER(PARTITION BY A , B , C  ORDER BY D ) - D)  GB 
          FROM T
        )
GROUP BY A , B , C , GB
ORDER BY TO_NUMBER(MIN(D))


by 마농 [2017.09.28 10:30:28]
MERGE INTO target_t a
USING
(
SELECT a, b, c
     , MIN(d) min_d
     , MAX(d) max_d
  FROM (SELECT a, b, c, d
             , ROW_NUMBER() OVER(ORDER BY d)
             - ROW_NUMBER() OVER(PARTITION BY a, b, c ORDER BY d) grp
          FROM source_t
         WHERE d >= (SELECT MAX(min_d) FROM target_t) -- 마지막 작업 이후부터 집계
        )
 GROUP BY a, b, c, grp
-- ORDER BY d1
) b
ON (a.a = b.a
AND a.b = b.b
AND a.c = b.c
AND a.min_d = b.min_d
)
WHEN MATCHED THEN
  UPDATE SET a.max_d = b.max_d
WHEN NOT MATCHED THEN
  INSERT VALUES (b.a, b.b, b.c, b.min_d, b.max_d)
;

 

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