'소계'에 해당되는 글 7

  1. 2008.04.14 [오라클] CALENDAR 를 이용한 소계 및 합계 구하는 쿼리

/*
    이 SQL문은 소계나 합계를 찍기 위해서 UNION ALL을 사용하는 방법이 있는반면에 오라클에서 지원해주는 CALENDAR 테이블을 이용하여 ROWNUM 함수명을 이용하여 소계나 합계를 구할수 있다.
 
여기에서의 쿼리는 *****에서 연말정산 징수및 환급 일람표를 작성하기 위하여 구현한것이다.
         - 부서별로 소계를 찍는다...
   
    ROWNUM을 2개 설정(여기서는 소계만을 찍는데 합계 까지 할려면 3개가 필요하다)
       개념 상으로   1.같은 데이타가 두배가 된다.  
                           (예로서 구하고자하는 데이타의 로우가 10개이면 ROWNUM 을 2로 하면 20개의 로우가 발생한다)
                          2. 1번째 ROWNUM은 각각의 데이타를 위한것이고 2번째 ROWNUM은 소계를 구하기 위한것이다.
      
       내부도식화하면  [A테이블]    [B 데이블] ====> 여기에서 나오는 결과값은   ===> GROUP BY 결과 값
                            NO  VALUE     ROWNUM       ROWNUM  NO  VALUE                 ROWNUM     NO   VALUE
                              A   10                 1                       1    A    10                                  1       A     10
                              B   10                 2                       1    B    10                                  1       B     10
                              C   10                                         1    C    10                                  1       C     10
                              D   10                                         1    D    10                                   1       D     10
                                                                               2    A    10                                    2             40
                                                                               2    B    10
                                                                               2    C    10
                                                                               2    D    10
     
     
*/    
 

SELECT DECODE(RCNT, 2, '1', '0'),    /*여기서는 그냥 RCNT 만해도 된다                          */
       DEPTCODE,                     /* 여기서는 부서코드로서 소계를 내기때문에 이렇게 하였다    */
       DEPTNAME,                     /* 부서명이다                                             */
       DECODE(RCNT, 2, '', EMPNO) AS EMPNO, /* RCNT(ROWNUM)이 1이면 각각의 데이타를 뿌리고 2이면 그룹을 하기위해서 값을 동일하게 만들어준다 */
       DECODE(RCNT, 2, '[ 소계 ]', NAME)  AS NAME,  /* 위의내용과 동일   여기서는 소계를 찍기에 미리 여기에서 표시해주었다 */
       DECODE(RCNT, 2, (TO_CHAR(COUNT) || '명'), RESNO)    AS RESNO, /* 위의내용과 동일   여기서는 부서별로 몇개의 소계인지를 찍기위해서 이렇게 표현 */
       SUM(DCSNTAXINCM)                               AS DCSNTAXINCM,    /* 여기에서는 그룹으로 묶인 부분은 합할것이고 */
       SUM(DCSNTAXINHA)                                AS DCSNTAXINHA,
       SUM(BLNCCLLCINCM)                             AS BLNCCLLCINCM,
       SUM(BLNCCLLCINHA)                               AS BLNCCLLCINHA
FROM   ( SELECT D.COUNT        AS COUNT,
                B.DEPTCODE     AS DEPTCODE,
                C.DEPTNAME     AS DEPTNAME,
                A.EMPNO        AS EMPNO,
                B.NAME         AS NAME,
                B.RESNO        AS RESNO,
                A.DCSNTAXINCM  AS DCSNTAXINCM,
                A.DCSNTAXINHA  AS DCSNTAXINHA,
                A.BLNCCLLCINCM AS BLNCCLLCINCM,
                A.BLNCCLLCINHA AS BLNCCLLCINHA
         FROM   EMPM190M A, EMPP001M B, EMPM074M C,
                ( SELECT DEPTCODE,COUNT(DEPTCODE) AS COUNT
                  FROM   EMPM190M A, EMPP001M B
                  WHERE  A.EMPNO = B.EMPNO
                  GROUP BY DEPTCODE
                ) D     /*  -----------------> 부서별로 몇개인지를 구하기위해서*/

         WHERE  A.EMPNO = B.EMPNO
           AND  A.WORKYY = :pWORKYY
           AND  B.DEPTCODE = C.DEPTCODE
           AND  B.DEPTCODE = D.DEPTCODE
       ) A,/*------------------------------------------------------------> A 테이블이 실제 데이타이다*/
       ( SELECT ROWNUM AS RCNT FROM CALENDAR WHERE ROWNUM < 3) B  /*-----> B 테이블은 CALENDAR 을 이용한 ROWNUM을 2개 구현 */
GROUP BY DECODE(RCNT, 2, '1', '0'),  -----> 그룹을 지어주므로 ROWNUM이 1인것은 각각의 데이타가나올것이고
         DEPTCODE,                                             ROWNUM이 2인 것은 그룹으로 묶어서 합계를 찍을 수있는 것이다.
         DEPTNAME,                                      
         DECODE(RCNT, 2, '', EMPNO),                    
         DECODE(RCNT, 2, '[ 소계 ]', NAME),              
         DECODE(RCNT, 2, (TO_CHAR(COUNT) || '명'), RESNO)  
ORDER BY DEPTCODE, EMPNO    --마지막으로 부서별로 정렬을 하여 소계가 순차적으로 찍히게 된다.