위 함수는 V9.7 FixPack4에서 새롭게 소개된 함수이다. 특정 컬럼 기준으로 그룹의 문자열 값 세트를 하나의 문자열로 집계하도록 하는 기능을 한다.

고객사쪽에서 문의가 와서 고민하다 위 함수가 생각이 나서 소개를 해 주었는데, 나름 의미가 있을 듯 해서 블로그에도 남겨 본다.

저장된 데이터

C1          C2          C3
----------- ----------- ---
          1           1 A
          1           1 B
          1           1 C
          1           2 D
          1           3 E

 

원하는 결과값

C1          C2          C3_SUM
----------- ----------- ------------
          1           1 A,B,C
          1           2 D
          1           3 E

 

LISTAPP() 함수를 쓰면 다음과 같이 간단한 SQL로 구현된다.

select c1,
         c2,
         substr(listagg(c3,',') within group(order by c3),1,12) as c3_sum
from t1
group by c1, c2

결과값

C1          C2          C3_SUM
----------- ----------- ------------
          1           1 A,B,C
          1           2 D
          1           3 E

 

만일 V9.7 FixPack4 미만이라 사용할 수 없는 경우라면?

본 SQL 경우에는 3개의 문자를 붙이는 경우가 최대라고 가정하고 구현된 SQL이다. Stored Procedure 나 사용자 함수(UDF)를 만들어서 구현한다면 조금은 간단한 SQL 되지 않을까 싶다.

select a.c1, a.c2, a.c5||','|| b.c3 c3
from t1 b,
(select a.c1, a.c2, a.c3, t1.c3 c4, a.c3 || ',' || t1.c3 c5
from t1,
    (select a.c1, a.c2, b.c3
           from (select c1,c2,count(c3) cnt from t1 group by c1, c2 having count(c3) > 1 ) a,
                (select c1,c2,c3 from t1)b
     where a.c1=b.c1 and a.c2=b.c2 fetch first 1 rows only) a
where a.c1 = t1.c1 and a.c2 = t1.c2 and a.c3 <> t1.c3  fetch first 1 rows only) a
where a.c1=b.c1 and a.c2=b.c2 and b.c3 <> a.c3 and b.c3 <> a.c4

union all

select c1, c2, max(c3) c3 from t1 group by c1,c2 having count(c3) = 1

결과값

C1          C2          C3
----------- ----------- -----------
          1           2 D
          1           3 E
          1           1 A,B,C

  3 record(s) selected.

 

테스트한 table 및 insert 문

db2 "create table t1 (c1 integer, c2 integer, c3 varchar(3))"
db2 "insert into t1 values (1,1,'A'),(1,1,'B'),(1,1,'C'),(1,2,'D'),(1,3,'E')"

+ Recent posts