'(DB) Oracle/SQL.통계-Pivot함수'에 해당되는 글 4건

  1. 2017.01.21 Oracle - PIVOT 컬럼 목록 구하기
  2. 2017.01.21 Oracle - PIVOT Grid.Header 목록 구하기
  3. 2017.01.21 Oracle - PIVOT 함수 - 컬럼2개인 경우 2
  4. 2017.01.21 Oracle - PIVOT 함수 - 컬럼1개인 경우

[ Oracle - PIVOT  컬럼 목록 구하기 ]

 

-- 정의   : PIVOT()함수를 사용할때 컬럼갯수를 알아야만 한다.
--          결과 컬럼을 정의해 주지 않으면 PIVOT()함수를 사용할 수 없다.
--          
--          월갯수(from~to)를 알수 없을 경우에는 PIVOT()함수를 사용할 없게 된다.
--          
--          그런데, Dynamic SQL 문장을 사용하게 되면 SQL 문장을 작성할 때는 컬럼을 정의하지 않고
--          PIVOT()함수 정의 된 SQL 문장을 실행하기 전에  
--          월 갯수를 파악하여  PIVOT()함수에 추가한다.
--          (즉, myBatis 에서  FOR PLAN_YM IN ($COLUMN_LIST$)  와 같이 함)

 


SELECT
 (CASE WHEN GRP_ID   = '0' THEN PLAN_YM
             
WHEN MM_COUNT <  6  THEN '소계'
             
WHEN MM_COUNT =  6 AND FIRST_SECOND_TYPE = '0' THEN '상반기'
             
WHEN MM_COUNT =  6 AND FIRST_SECOND_TYPE = '1' THEN '하반기'
             
WHEN MM_COUNT = 12                             THEN '년계'
             
ELSE '총계' END) AS PLAN_YM
     , FIRST_SECOND_TYPE         
--0:상반기,  1:하반기
     , MM_COUNT                  
--1:Table 컬럼 sum()값.  2이상:소계, 합계 컬럼임
     , GRP_ID                    
--GROUPING_ID()함수 결과 값.
     , COL_ROWNUM                
--컬럼 ROWNUM
  
FROM
 (
        
SELECT YEAR_DATA
             , PLAN_YM
             , FIRST_SECOND_TYPE
             , 
COUNT(FIRST_SECOND_TYPE) AS MM_COUNT
             , 
GROUPING_ID(YEAR_DATA, FIRST_SECOND_TYPE, PLAN_YM) AS GRP_ID
          
FROM (
                --2013.10 ~ 201502 월까지 존재 하는 테이블일 경우
                
WITH YY_MM AS
                    ( 
SELECT TO_CHAR(ADD_MONTHS(TO_DATE('201310', 'YYYYMM'), ROWNUM), 'YYYYMM') AS PLAN_YM
                        
FROM DUAL
                      CONNECT BY LEVEL <= 17 )
                
SELECT SUBSTR(B.PLAN_YM, 1,4)                   AS YEAR_DATA
                     , B.PLAN_YM                                
AS PLAN_YM
                     , 
FLOOR ((SUBSTR(B.PLAN_YM,5,2) - 1) / 6)  AS FIRST_SECOND_TYPE
                  
FROM YY_MM B
               )
        
GROUP BY ROLLUP(YEAR_DATA, FIRST_SECOND_TYPE, PLAN_YM)
       )
 
WHERE GRP_ID IN ('0', '1', '7') 
    
OR (MM_COUNT = 12 AND GRP_ID = 3) ;

 

 

Posted by 농부지기
,

[ Oracle - PIVOT Grid.Header 목록 구하기 ]

 

-- 정의   : 반복 컬럼이 1 ~ 3개 일 경우
--          PIVOT 함수 사용중  시작년월~종료년월 까지 자료를 조회 할 경우
-- 사용처 : PIVOT 조회결과를 화면에 보여 주려면  화면.Grid.Header를 dynamic하게 그려줘야 된다.
--          이때 고정컬럼을 항상 정해졌기 때문에 문제가 없고
--          반복컬럼과 중간에 소계, 합계가 들어 갈 경우 
--          아래 SQL문 결과를 통해서 Grid.Header를 그려줄 수 있다.

 


SELECT (CASE WHEN GRP_ID   = '0' THEN PLAN_YM
             
WHEN MM_COUNT <  6  THEN '소계'
             
WHEN MM_COUNT =  6 AND FIRST_SECOND_TYPE = '0' THEN '상반기'
             
WHEN MM_COUNT =  6 AND FIRST_SECOND_TYPE = '1' THEN '하반기'
             
WHEN MM_COUNT = 12                             THEN '년계'
             
ELSE '총계' END) AS PLAN_YM
       
--실 컬럼명은 변수로 받아야 됨
     , 
DECODE(COL_GUBN_GRP, 1, '비중', 2, '매출액', 3, '이익금') AS COL_NAME
     , FIRST_SECOND_TYPE         
--0:상반기,  1:하반기
     , MM_COUNT                  
--1:Table 컬럼 sum()값.  2이상:소계, 합계 컬럼임
     , GRP_ID                    
--GROUPING_ID()함수 결과 값.
     , COL_ROWNUM                
--컬럼 ROWNUM
     , COL_GUBN_GRP              
--반복컬럼이 1개 이상일 경우 순서
  
FROM (
        
WITH YY_MM AS
           (
            
SELECT YEAR_DATA
                 , PLAN_YM
                 , FIRST_SECOND_TYPE
                 , 
COUNT(FIRST_SECOND_TYPE) AS MM_COUNT
                 , 
GROUPING_ID(YEAR_DATA, FIRST_SECOND_TYPE, PLAN_YM) AS GRP_ID
              
FROM (SELECT SUBSTR(A.PLAN_YM, 1,4)                     AS  YEAR_DATA
                         , A.PLAN_YM                               
   AS PLAN_YM
                         , 
FLOOR ((SUBSTR(A.PLAN_YM,5,2) - 1) / 6)    AS  FIRST_SECOND_TYPE
                      
FROM ( --2013.10 ~ 201502 월까지 존재 하는 테이블
                             
SELECT TO_CHAR(ADD_MONTHS(TO_DATE('201310', 'YYYYMM'), ROWNUM), 'YYYYMM') AS PLAN_YM
                               
FROM DUAL
                            
CONNECT BY LEVEL <= 17 
                           ) A
                   )
            
GROUP BY ROLLUP(YEAR_DATA, FIRST_SECOND_TYPE, PLAN_YM)
           )
        
SELECT PLAN_YM
             , FIRST_SECOND_TYPE
             , MM_COUNT
             , GRP_ID
             
--** 맨 앞쪽  1은  변수로 받아야 됨. (반복컬럼 갯수 임)
             , 
DECODE(3, 1, ROWNUM, 2, (ROWNUM * 2) - 1, (ROWNUM * 3) - 2) AS COL_ROWNUM   
             , 1      
AS COL_GUBN_GRP
          
FROM  YY_MM
         
WHERE  GRP_ID IN ('0', '1', '7') OR (MM_COUNT = 12 AND GRP_ID = 3)

        
UNION ALL

        
SELECT PLAN_YM
             , FIRST_SECOND_TYPE
             , MM_COUNT
             , GRP_ID
             
--** 맨 앞쪽  2는  변수로 받아야 됨. (반복컬럼 갯수 임)
             , 
DECODE(3, 2, (ROWNUM * 2) - 0, (ROWNUM * 3) - 1) AS COL_ROWNUM  
             , 2      
AS COL_GUBN_GRP
          
FROM  YY_MM
         
WHERE ( GRP_ID IN ('0', '1', '7') OR (MM_COUNT = 12 AND GRP_ID = 3) ) 
           
AND 2 <= 2    --** 오른쪽  2는  변수로 받아야 됨. (반복컬럼 갯수 임)

       
UNION ALL

        
SELECT PLAN_YM
             , FIRST_SECOND_TYPE
             , MM_COUNT
             , GRP_ID
             , (
ROWNUM * 3) - 0 AS COL_ROWNUM  
             , 3          
      AS COL_GUBN_GRP
          
FROM  YY_MM
         
WHERE ( GRP_ID IN ('0', '1', '7') OR (MM_COUNT = 12 AND GRP_ID = 3) ) 
           
AND 3 = 3    --** 오른쪽  3은  변수로 받아야 됨. (반복컬럼 갯수 임)
       )
 ORDER BY COL_ROWNUM ;
 

 

Posted by 농부지기
,

 

 

[ Oracle - PIVOT 함수 - 컬럼2개인 경우 ]

 

1. 정의 : 매장별, 월별 이익금, 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼을 기술하지 않은 경우
           2. PIVOT 컬럼이 두 개 인 경우
           3. SUM() 한 후 컬럼을 지정 (이때 지정하지 않으면  오류 발생)

 


WITH
 SALE_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
          
FROM SALE_DATA
        )
PIVOT (SUM(PROFIT_AMT)   AS PT_AMT, SUM(SALE_AMT) AS SA_AMT   -- <-- 이곳에 컬럼 지정
                       FOR
 SALE_YM IN ('201401'               -- <-- 이곳에 컬럼을 지정 하지 않은 경우
                                     , '201402'
                                     , '201403'
                                     , '201404'
                                     , '201405'
                                     , '201406'

                                     )
      );
 

결과


결과 컬럼이 : 년월 과 AS 후 컬럼이 결합되어  이익금컬럼과  매출액컬럼이 쌍으로 해서 반복되어 나온다..

                

 


  

2. 정의 : 매장별, 월별 이익금, 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼을 기술 한 경우
           2. PIVOT 컬럼이 두 개 인 경우
           3. SUM() 한 후 컬럼을 지정 (이때 지정하지 않으면  오류 발생)

 


WITH
 SALE_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
             , SALE_AMT
          
FROM SALE_DATA
        )
PIVOT (SUM(PROFIT_AMT)   AS PT_AMT, SUM(SALE_AMT) AS SA_AMT   -- <-- 이곳에 컬럼 지정
                       FOR
 SALE_YM IN ('201401' AS IDX1       -- <-- 이곳에 컬럼 지정
                                     , '201402'
 AS IDX2
                                     , '201403'
 AS IDX3
                                     , '201404'
 AS IDX4
                                     , '201405'
 AS IDX5
                                     , '201406'
 AS IDX6
                                     )
      );
 

결과
결과 컬럼이 : 년월 후의 AS 컬럼과  SUM() 후 AS컬럼이 결합되어  
              이익금컬럼과  매출액컬럼이 쌍으로 해서 반복되어 나온다..
            
 

 


  

Posted by 농부지기
,

[ Oracle - PIVOT 함수 - 컬럼1개인 경우 ]

 

1. 정의 : 매장별, 월별 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼을 기술하지 않은 경우
           2. PIVOT 컬럼이 한 개 인 경우
           3. SUM() 한 후 컬럼을 지정하지 않은 경우

 


WITH
 MONTH_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
          
FROM MONTH_DATA
        )
PIVOT (SUM(PROFIT_AMT)                                   -- <-- 이곳에 컬럼을 지정 하지 않은 경우
                       FOR
 SALE_YM IN ('201401'          -- <-- 이곳에 컬럼을 지정 하지 않은 경우
                                     , '201402'
                                     , '201403'
                                     , '201404'
                                     , '201405'
                                     , '201406'

                                     )
      );

결과
결과 컬럼이 : 년월로 자동처리 된다.
              이 컬럼이 숫자형이라서 single(')quote가 존재하고, java등에서 어떻게 처리 될지 모르겠음.

                
 


  

2. 정의 : 매장별, 월별 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼 기술 한 경우
           2. PIVOT 컬럼이 한 개 인 경우

 


WITH
 MONTH_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
          
FROM MONTH_DATA
        )
PIVOT (SUM(PROFIT_AMT)                                                -- <-- 이곳에 컬럼을 지정 하지 않은 경우
                       FOR SALE_YM IN ('201401' AS PI_201401          -- <-- 이곳에 컬럼을 지정 한 경우
                                     , '201402'
 AS PI_201402
                                     , '201403'
 AS PI_201403
                                     , '201404'
 AS PI_201404
                                     , '201405'
 AS PI_201405
                                     , '201406'
 AS PI_201406
                                     )
      );
 

결과
결과 컬럼이 : 지정한 명칭으로 컬럼이 조회 된다.



  

3. 정의 : 매장별, 월별 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼을 기술하지 않은 경우
           2. PIVOT 컬럼이 한 개 인 경우
           3. SUM() 한 후 컬럼을 지정하지 않은 경우

 


WITH
 MONTH_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
          
FROM MONTH_DATA
        )
PIVOT (SUM(PROFIT_AMT)  AS PT_AMT                        -- <-- 이곳에 컬럼을 지정 한 경우 
                       FOR
 SALE_YM IN ('201401'          -- <-- 이곳에 컬럼을 지정 하지 않은 경우
                                     , '201402'
                                     , '201403'
                                     , '201404'
                                     , '201405'
                                     , '201406'

                                     )
      );
 

결과
결과 컬럼이 : PIVOT컬럼이  앞쪽  년월 + PT_AMT(AS컬럼) 조합되어 처리 된다.
              이 결과 컬럼도  년월(숫자형) + PT_AMT 라서 앞쪽이 숫자라 JAVA단에서 어떻게 처리 될지 모르겠음.


  

4. 정의 : 매장별, 월별 매출액 조회(2014.01 ~ 2014.06)

  - 참고 : 1. PIVOT 년월 에  컬럼 기술 한 경우
           2. PIVOT 컬럼이 한 개 인 경우
           3. SUM() 한 후 컬럼을 지정한 경우

 


WITH
 MONTH_DATA AS
    ( 
SELECT DECODE(MOD(ROWNUM, 3), 0, '강남점', 1, '역삼점', 2, '평촌점') AS SHOP_NM
           , 
TO_CHAR(ADD_MONTHS(TO_DATE('201401', 'YYYYMM'), ROUND(dbms_random.value(0,5),0)), 'YYYYMM') AS SALE_YM
           , 
ROUND(dbms_random.value(   1, 5000),0) AS PROFIT_AMT
           , 
ROUND(dbms_random.value(5000,10000),0) AS SALE_AMT
        FROM DUAL
      
CONNECT  BY LEVEL <= 25 )
SELECT *
  
FROM (
        
SELECT SHOP_NM
             , SALE_YM
             , PROFIT_AMT
          
FROM MONTH_DATA
        )
PIVOT (SUM(PROFIT_AMT)  AS PT_AMT                                     -- <-- 이곳에 컬럼을 지정 한 경우
                       FOR SALE_YM IN ('201401' AS PI_201401          -- <-- 이곳에 컬럼을 지정 한 경우
                                     , '201402'
 AS PI_201402
                                     , '201403'
 AS PI_201403
                                     , '201404'
 AS PI_201404
                                     , '201405'
 AS PI_201405
                                     , '201406'
 AS PI_201406
                                     )
      );
 

결과


결과 컬럼이 : 지정한 명칭 과 AS 컬럼이 결합되어 결과 컬럼이 만들어 진다.


  

 

Posted by 농부지기
,