2008. 10. 8. 15:31

[oracle]각각의 합과 총합을 Reporting하는 쿼리

/*  UNION, UNION ALL
    UNION : 중복을 제거한 합집합
    UNION ALL : 모든 합집합         */
 SELECT 1 dummy FROM DUAL
  UNION ALL
 SELECT 2 dummy FROM DUAL

/*  Cartesian Product    */  
 SELECT *
   FROM ( SELECT 1 dummy FROM DUAL
           UNION ALL
    SELECT 2 dummy FROM DUAL
  ) a,
        ( SELECT deptno, count(*) cnt
       FROM emp
     GROUP BY deptno
  ) b
 
/*  각각의 합과 총합을 Reporting    */
 SELECT Decode(a.dummy, 1, Nvl(b.dname, 'Null'), 'Sum'),
        Decode(a.dummy, 1, Max(b.cnt), Sum(b.cnt))
   FROM ( SELECT 1 dummy FROM DUAL
           UNION ALL
    SELECT 2 dummy FROM DUAL
  ) a,
        ( SELECT b1.deptno, dname, count(*) cnt
       FROM emp b1, dept b2
     WHERE b1.deptno = b2.deptno
     GROUP BY b1.deptno, dname
  ) b
  GROUP BY a.dummy, Decode(a.dummy, 1, Nvl(b.dname, 'Null'), 'Sum')
  ORDER BY a.dummy, Decode(a.dummy, 1, Nvl(b.dname, 'Null'), 'Sum')
 
/*  각각의 합과 총합을 Reporting    */ 
SELECT a.sys_name 검사항목,
       sum(a.cnt)  총갯수,
       sum(decode(a.stat, '01', cnt, 0)) 운용,
       sum(decode(a.stat, '03', cnt, 0)) 예비운용,
       NULL 최종연동시작시간,
       NULL 최종연동완료시간
  FROM ( SELECT 'iNetPost' sys_name,
                stat,
                count(*) cnt
           FROM tb_office@np_link
          WHERE stat IN ('01', '03')
          GROUP BY stat
       ) a
 GROUP BY a.sys_name

2008. 10. 8. 15:31

[oracle]테이블 정의서를 작성하기 위한 프로시저

CREATE OR REPLACE PROCEDURE all_tabspec_procedure IS

 v_column_id   user_tab_columns.column_id%TYPE;
 v_column_name  user_tab_columns.column_name%TYPE;
 v_data_type   user_tab_columns.data_type%TYPE;
 v_data_length  user_tab_columns.data_length%TYPE;
 v_data_precision user_tab_columns.data_precision%TYPE;
 v_data_scale  user_tab_columns.data_scale%TYPE;  
 v_nullable   user_tab_columns.nullable%TYPE;
 v_data_default  user_tab_columns.data_default%TYPE;

 v_data_length_num VARCHAR2(10);
 


 CURSOR table_spec_cursor(in_table_name user_tab_columns.table_name%TYPE) IS

  select LTRIM(RTRIM(column_id)) NO,
      LTRIM(RTRIM(column_name)) ITEM_NAME, LTRIM(RTRIM(data_type)) 속성,
      LTRIM(RTRIM(data_length)) 길이, data_precision 길이_P,
      data_scale 길이_S, nullable 널, data_default 디폴트
  from user_tab_columns
  where table_name = in_table_name
  order by column_id;


 CURSOR all_object_cursor IS
--  select object_name from user_objects where object_type in('TABLE', 'VIEW') ;
--  select object_name from user_objects where object_type = 'TABLE' ;
--  select object_name from user_objects where object_type = 'VIEW' ;
  select distinct object_name from user_objects where object_name in ('ANNUITY', 'ANNUITY_DET', 'BANK', 'BASE_DET', 'BENEFIT_HIST',
    'CARE', 'CARE_DET', 'CHANGE', 'CHANGE_DET', 'COMN_KEEP', 'COUPL', 'FAMILY', 'GROW', 'GROW_DET',
    'LOAN', 'PAY_HIST', 'REFER', 'SPECIAL_CON_DET', 'TERM_DET');

BEGIN

 DBMS_OUTPUT.ENABLE(1000000);

 FOR allobj_cursor_rec IN all_object_cursor LOOP

  OPEN table_spec_cursor(allobj_cursor_rec.object_name);
 
  /* OBJECT NAME(TABLE OR VIEW) 인쇄*/
  DBMS_OUTPUT.PUT_LINE(' ');
  DBMS_OUTPUT.PUT_LINE(' ');
  DBMS_OUTPUT.PUT_LINE('====================   ' || allobj_cursor_rec.object_name || '   ====================');

  /* TYTLE 인쇄*/
  DBMS_OUTPUT.PUT_LINE('NO' || ',' || '   ' ||  'COLUMN_NAME' || ',' || '                      ' ||
          '속성' || ',' || '    ' || '길이' ||  ',' || '널'  ||  ',' || '       ' || '디폴트');

  LOOP
   FETCH table_spec_cursor
    INTO v_column_id, v_column_name, v_data_type, v_data_length, v_data_precision, v_data_scale, v_nullable, v_data_default;
   EXIT WHEN table_spec_cursor%NOTFOUND;

   /* (1)데이터Type이「NUMBER」인 경우는
     ① data_scale이0인 경우는data_precision을data_length로 지정    
                                              ② data_scale이NULL인 경우는data_length치를 그대로 사용
     ③ data_scale이0혹은NULL이 아닌 경우는「data_precision|data_scale」을data_length로 지정한다
        여기서는v_data_length_num변수를 사용(data_length는NUMBER TYPE)
     ④ data_scale이0이아닌 경우는data_precision을data_length로서 사용
      (2)데이터Type이「NUMBER」가 아닌 경우는data_length치를 그대로 사용
   IF v_data_type = 'NUMBER' THEN
    IF v_data_scale = 0 THEN
     v_data_length := v_data_precision;
     DBMS_OUTPUT.PUT_LINE(v_column_id || ',' || '   ' || RPAD(LTRIM(RTRIM(v_column_name)),30,' ') || ','|| '   ' ||
       RPAD(v_data_type,10,' ') || ',' || '   ' || v_data_length || ',' || '   ' ||
       RPAD(v_nullable,1,' ') || ',' || '   ' || LTRIM(RTRIM(v_data_default)));
    ELSE
     v_data_length_num := CONCAT(CONCAT(TO_CHAR(v_data_precision),'|'),TO_CHAR(v_data_scale));

     DBMS_OUTPUT.PUT_LINE(v_column_id || ',' || '   ' || RPAD(LTRIM(RTRIM(v_column_name)),30,' ') || ','|| '   ' ||
         RPAD(v_data_type,10,' ') || ',' || '   ' || v_data_length_num || ',' || '   ' ||
         RPAD(v_nullable,1,' ') || ',' || '   ' || LTRIM(RTRIM(v_data_default)));

    END IF;
   ELSE
    v_data_length := v_data_length;
    DBMS_OUTPUT.PUT_LINE(v_column_id || ',' || '   ' || RPAD(LTRIM(RTRIM(v_column_name)),30,' ') || ','|| '   ' ||
      RPAD(v_data_type,10,' ') || ',' || '   ' || v_data_length || ',' || '   ' ||
      RPAD(v_nullable,1,' ') || ',' || '   ' || LTRIM(RTRIM(v_data_default)));
   END IF;

  END LOOP;
  CLOSE table_spec_cursor;
   
 END LOOP;

END all_tabspec_procedure;
/

2008. 10. 8. 15:30

[oracle]데이트를 세로에서 가로로 표현하기(Decode 활용)

세로로 나열된 데이터를 가로로 보여주는 것을 영어로 Pivioting 시킨다고 표현을 하더군요.

SUM(DECODE(...)) 를 보셨는지 모르겠네요.

강력한 기능이죠..이걸 이용하면 pivoting 이 가능합니다.

제가 테스트한 데이터와 쿼리를 올립니다.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

========
# 데이터
========
                           acct        month       amt        
                      ---------- ----------- -----------
    1           1          10
    1           2          10
    1           3          10
    1           4          10
    1           5          10
    1           6          10
    1           7          10
    1           8          10
    1           9          10
    1          10          10
    1          11          10
    1          12          10
    2           1          20
    2           2          20
    2           3          20
    2           4          20
    2           5          20
    2           6          20
    2           7          20
    2           8          20
    2           9          20
    2          10          20
    2          11          20

============
# 데이터 생성
============

CREATE TABLE test1( acct NUMBER(2), month NUMBER(2), amt NUMBER(2));
   
   
INSERT INTO test1 VALUES(1,1,10);
INSERT INTO test1 VALUES(1,2,10);
INSERT INTO test1 VALUES(1,3,10);
INSERT INTO test1 VALUES(1,4,10);
INSERT INTO test1 VALUES(1,5,10);
INSERT INTO test1 VALUES(1,6,10);
INSERT INTO test1 VALUES(1,7,10);
INSERT INTO test1 VALUES(1,8,10);
INSERT INTO test1 VALUES(1,9,10);
INSERT INTO test1 VALUES(1,10,10);
INSERT INTO test1 VALUES(1,11,10);
INSERT INTO test1 VALUES(1,12,10);
INSERT INTO test1 VALUES(2,1,20);
INSERT INTO test1 VALUES(2,2,20);
INSERT INTO test1 VALUES(2,3,20);
INSERT INTO test1 VALUES(2,4,20);
INSERT INTO test1 VALUES(2,5,20);
INSERT INTO test1 VALUES(2,6,20);
INSERT INTO test1 VALUES(2,7,20);
INSERT INTO test1 VALUES(2,8,20);
INSERT INTO test1 VALUES(2,9,20);
INSERT INTO test1 VALUES(2,10,20);
INSERT INTO test1 VALUES(2,11,20);
INSERT INTO test1 VALUES(2,12,20);

==================================
# 쿼리 1 : SUM(DECODE(...)) 이용
==================================
SELECT acct,
       SUM(DECODE(month,1,amt,0)) as MON1,
       SUM(DECODE(month,2,amt,0)) as MON1,
       SUM(DECODE(month,3,amt,0)) as MON1,
       SUM(DECODE(month,4,amt,0)) as MON1,
       SUM(DECODE(month,5,amt,0)) as MON1,
       SUM(DECODE(month,6,amt,0)) as MON1,
       SUM(DECODE(month,7,amt,0)) as MON1,
       SUM(DECODE(month,8,amt,0)) as MON1,
       SUM(DECODE(month,9,amt,0)) as MON1,
       SUM(DECODE(month,10,amt,0)) as MON1,
       SUM(DECODE(month,11,amt,0)) as MON1,
       SUM(DECODE(month,12,amt,0)) as MON1
FROM test1
GROUP BY acct;     

        
==================================
# 쿼리 2 : 다른 함수 이용
==================================
SELECT acct,
   SUM(amt * (1 - ABS(SIGN(month - 1)))) as Mon1,
   SUM(amt * (1 - ABS(SIGN(month - 2)))) as Mon2,
   SUM(amt * (1 - ABS(SIGN(month - 3)))) as Mon3,
   SUM(amt * (1 - ABS(SIGN(month - 4)))) as Mon4,
   SUM(amt * (1 - ABS(SIGN(month - 5)))) as Mon5,
   SUM(amt * (1 - ABS(SIGN(month - 6)))) as Mon6,
   SUM(amt * (1 - ABS(SIGN(month - 7)))) as Mon7,
   SUM(amt * (1 - ABS(SIGN(month - 8)))) as Mon8,
   SUM(amt * (1 - ABS(SIGN(month - 9)))) as Mon9,
   SUM(amt * (1 - ABS(SIGN(month - 10)))) as Mon10,
   SUM(amt * (1 - ABS(SIGN(month - 11)))) as Mon11,
   SUM(amt * (1 - ABS(SIGN(month - 12)))) as Mon12
FROM test1
GROUP BY acct;

두번째 쿼리 만든사람 대단하지 않습니까..
http://www.ncst.ernet.in/~sybase/faq/Q2.3.html 에 있길래 가져왔는데,
아주 감탄스럽습니다..

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

이상 제가 테스트한 내용이구요, 여러분들의 필요에 맞게 활용하시면 되겠네요.
SUM 뿐만 아니라 AVG, MAX도 DECODE함수와 함께 쓰일 수 있습니다.
정보가 더 필요하다 생각되시면 찾아보면 될거같군요.

sample1)
select codeclass 망구분, codedisp 장비종류, codedesc 장비설명,
       sum(decode(equipstatus, '01', cnt, 0)) 운용,
       sum(decode(equipstatus, '02', cnt, 0)) 철거예정,
       sum(decode(equipstatus, '05', cnt, 0)) 불용대상,
       sum(cnt) 시스템수
  from
(SELECT d.codedisp codeclass, c.codedisp , c.codedesc, m.equipstatus, count(*) cnt
  FROM oss_equipmast m, oss_codemast c,oss_codemast d
 WHERE equiptypecode not in ('BTS')
   AND c.category = 'EquipType'
   AND m.equiptypecode = c.code
   AND d.category = 'CodeClass'
   AND c.class = d.code
   AND c.class != 'TRANSMISSION'
 GROUP BY d.codedisp,c.codedisp, c.codedesc, m.equipstatus
)
GROUP BY codeclass, codedisp, codedesc
ORDER BY 1,2;


SELECT MODEL_SEQ_NO
     , MIN(DECODE(EXAM_TYPE, '00002', PLATFORM_FAIL, NULL))    PLATFORM_FAIL
  , MIN(DECODE(EXAM_TYPE, '00003', FUNC_FAIL, NULL))    FUNC_FAIL
  FROM (SELECT A.MODEL_SEQ_NO
       , A.EXAM_TYPE
             , A.GEREXM_LOOP_TIME || '차'|| '(' || SUM(DECODE(A.EXAM_TYPE, '00002', DECODE( C.TESTRESULT_CODE,'00002',DECODE(C.EXAMSTD_SN, 'EF', 0, 1),0 ), 0) ) || ')'  PLATFORM_FAIL     --플랫폼검수불합격
             , A.GEREXM_LOOP_TIME || '차'|| '(' || SUM(DECODE(A.EXAM_TYPE, '00003', DECODE( C.TESTRESULT_CODE,'00002',DECODE(C.EXAMSTD_SN, 'EF', 0, 1),0 ), 0) ) || ')'  FUNC_FAIL         --기능검수불합격
          FROM T_PE_EXAM_INFO A         -- 현재차수
             , (SELECT MODEL_SEQ_NO, EXAM_TYPE, MAX(GEREXM_LOOP_TIME) GEREXM_LOOP_TIME FROM T_PE_EXAM_INFO WHERE MODEL_SEQ_NO = :MODEL_SEQ_NO AND EXAM_MOTION_STATUS = '00004' GROUP BY MODEL_SEQ_NO, EXAM_TYPE ) B         -- 이전차수
             , T_PE_EXAMSTD_RESULT C
         WHERE 1 = 1
           AND A.MODEL_SEQ_NO = :model_seq_no
           AND A.MODEL_SEQ_NO = B.MODEL_SEQ_NO
           AND A.EXAM_TYPE = B.EXAM_TYPE
     AND A.GEREXM_LOOP_TIME = B.GEREXM_LOOP_TIME
           AND A.MODEL_SEQ_NO = C.MODEL_SEQ_NO
           AND A.EXAM_TYPE = C.EXAM_TYPE
           AND A.GEREXM_LOOP_TIME =C.GEREXM_LOOP_TIME
         GROUP BY A.MODEL_SEQ_NO, A.EXAM_TYPE, A.GEREXM_LOOP_TIME)
 GROUP BY MODEL_SEQ_NO;
 
 
 
SELECT VM.MODEL_SEQ_NO
     , VM.GEREXM_LOOP_TIME || '차'|| '(' || SUM(DECODE( TESTRESULT_CODE,'00002',DECODE(EXAMSTD_SN, 'EF', 0, 1),0 )) || ')'  PLATFORM_FAIL
  , V2.FUNC_FAIL
  FROM (SELECT MODEL_SEQ_NO, EXAM_TYPE, MAX(GEREXM_LOOP_TIME) GEREXM_LOOP_TIME
          FROM T_PE_EXAM_INFO
       WHERE MODEL_SEQ_NO = :MODEL_SEQ_NO
     AND EXAM_TYPE = '00002'
     AND EXAM_MOTION_STATUS = '00004'
    GROUP BY MODEL_SEQ_NO, EXAM_TYPE) VM
     , T_PE_EXAMSTD_RESULT V1
     , (SELECT A1.MODEL_SEQ_NO
             , A1.GEREXM_LOOP_TIME || '차'|| '(' || SUM(DECODE( A2.TESTRESULT_CODE,'00002',DECODE(A2.EXAMSTD_SN, 'EF', 0, 1),0 )) || ')'  FUNC_FAIL
          FROM (SELECT MODEL_SEQ_NO, EXAM_TYPE, MAX(GEREXM_LOOP_TIME) GEREXM_LOOP_TIME
                  FROM T_PE_EXAM_INFO
                 WHERE MODEL_SEQ_NO = :MODEL_SEQ_NO
                   AND EXAM_TYPE = '00003'
                   AND EXAM_MOTION_STATUS = '00004'
                 GROUP BY MODEL_SEQ_NO, EXAM_TYPE) A1
             , T_PE_EXAMSTD_RESULT A2
         WHERE 1 = 1
           AND A1.MODEL_SEQ_NO = A2.MODEL_SEQ_NO
           AND A1.EXAM_TYPE = A2.EXAM_TYPE
           AND A1.GEREXM_LOOP_TIME = A2.GEREXM_LOOP_TIME
         GROUP BY A1.MODEL_SEQ_NO, A1.GEREXM_LOOP_TIME) V2
 WHERE 1 = 1
   AND VM.MODEL_SEQ_NO = :MODEL_SEQ_NO
   AND VM.MODEL_SEQ_NO = V1.MODEL_SEQ_NO
   AND VM.EXAM_TYPE = V1.EXAM_TYPE
   AND VM.GEREXM_LOOP_TIME =V1.GEREXM_LOOP_TIME
   AND VM.MODEL_SEQ_NO = V2.MODEL_SEQ_NO
 GROUP BY VM.MODEL_SEQ_NO, VM.GEREXM_LOOP_TIME, V2.FUNC_FAIL
;