2011-9-2

informatica 列转行

 informatica powercenter学习笔记(五)

上一篇 / 下一篇  2010-11-22 16:33:14 / 精华(1) / 置顶(1) / 个人分类:INFORMATICA POWER CENTER

查看( 190 ) / 评论( 7 )

以前在做DBA时在DB里写过行转列,列转行的CODE.这两天做了一下测试用INFORMATICA来实现行列互换的功能。

列转行的SQL实现

ENV: RMDB

TABLESALES

 STORENAME QUARTER1 QUARTER2 QUARTER3 QUARTER4

 STORE1                  100                 300                 500                 700

 STORE2                  200                 400                 600                 800

SOLUTION

 

SELECT STORENAME,QUARTER1 AS SALES, 1 AS QUARTER

FROM SALES

GROUP BY STORENAME,QUARTER1

UNION

SELECT STORENAME,QUARTER2 AS SALES, 2 AS QUARTER

FROM SALES

GROUP BY STORENAME,QUARTER2

UNION

SELECT STORENAME,QUARTER3 AS SALES, 3 AS QUARTER

FROM SALES

GROUP BY STORENAME,QUARTER3

UNION

SELECT STORENAME,QUARTER4 AS SALES, 4 AS QUARTER

FROM SALES

GROUP BY STORENAME,QUARTER4

 

 

列转行的INFORMATICA实现

 

1 SOURCE TABLES导入MAPING

2 SQLQUALIFER读取数据

3 NORMALIZER实现对应的列行转换,在NORMALIZER属性里设置STORENAME,QUARTER DATA(LEVEL 1每季度的销售值SALESLEVEL2. QUARTER DATAOCCURS值设为4就可实现列行转换

 

 

二  行转列的SQL实现

ENV:

createtablesales2(storenamevarchar(20),

salesnumber(9),quarternumber(9))

select*fromsales2

SOLUTION:

SELECTSTORENAME,

 MAX(CASEWHENQUARTER=1THENSALESELSE0END)QUARTER1,

 MAX(CASEWHENQUARTER=2THENSALESELSE0END)QUARTER2,

 MAX(CASEWHENQUARTER=3THENSALESELSE0END)QUARTER3,

 MAX(CASEWHENQUARTER=4THENSALESELSE0END)QUARTER4

 FROMSALES2

 GROUPBYSTORENAME

 ORDERBYSTORENAME

INFORMATICA实现

1       导入源表SALES2

2       SQLQULIFER读取数据

3       EXPERSSION TRANSFORMATION来判断QUARTER值来取SALES

   4  用聚合函数来取出判断后的最大值,即真正的SALES

   

5导入到目标表或目标文件后即实现了行转列的功能。


--
we drink green tea

oracle 列转行

oracle 列转行

2008-04-09

转载 
方法一:
----------------------------------------------------------------
---Muti-row to line(col2row)
----------------------------------------------------------------
create or replace type str_tab is table of varchar2(20);
/
grant all on str_tab to public;
create public synonym str_tab for str_tab;
create or replace function col2row(pv in str_tab) return varchar2
is
  ls varchar2(4000);
begin
  for i in 1..pv.count loop
    ls := ls || pv(i);
  end loop;
  return ls;
end;
/
grant execute on col2row to public;
create public synonym col2row for col2row;
----------------------------------------------------------------
--multi column,convert one column base on another column, for example
----------------------------------------------------------------
create table t(id number,name varchar2(10));
insert into t values(1,'Joan');
insert into t values(1,'Jack');
insert into t values(1,'Tom');
insert into t values(2,'Rose');
insert into t values(2,'Jenny');
---------------------------------------------------------------
SQL(c3dev)>select * from t;
        ID NAME
---------- ----------
         1 Joan
         1 Jack
         1 Tom
         2 Rose
         2 Jenny
---------------------------
--column to row
---------------------------
SQL(c3dev)>column names format a80;
SQL(c3dev)>set line 120
SQL(c3dev)>select t0.id,
  2     col2row(cast(multiset(select name from t where t.id = t0.id) as str_tab)) names 
  3  from (select distinct id from t) t0;
        ID NAMES
---------- --------------------------------------------------------------------------------
         1 JoanJackTom
         2 RoseJenny

----------------------------------------------------------------
--single column,convert multil row to one row, for example
----------------------------------------------------------------
create table t1(name varchar2(20));
insert into t1 values('Chen');
insert into t1 values('Chuan');
insert into t1 values('Zhong');
SQL(c3dev)>select * from t1;
NAME
--------------------
Chen
Chuan
Zhong
---------------------------
--column to row
---------------------------
select col2row(cast(multiset(select name from t1) as str_tab)) names from t1 where rownum=1
SQL(c3dev)>select col2row(cast(multiset(select name from t1) as str_tab)) names from t1 where rownum=1;
NAMES
--------------------------------------------------------------------------------
ChenChuanZhong

--if need to add list separator
SQL(c3dev)>select col2row(cast(multiset(select name||' ' from t1) as str_tab)) names from t1 where rownum=1;
NAMES
--------------------------------------------------------------------------------
Chen  Chuan Zhong
 
方法二:
create table t2(col1 varchar2(10),col2 varchar2(10));
insert into t2 values('001','vl1');
insert into t2 values('001','vl2');
insert into t2 values('001','vl3');
insert into t2 values('002','vl1');
insert into t2 values('002','vl2');
SELECT COL1,LTRIM(MAX(SYS_CONNECT_BY_PATH(COL2,',')),',') COL2
 FROM
 (
 SELECT COL1,COL2,MIN(COL2) OVER(PARTITION BY COL1) COL2_MIN,
 (ROW_NUMBER() OVER(ORDER BY COL1,COL2))+(DENSE_RANK() OVER (ORDER BY COL1)) NUMID
 FROM T2
 )
 START WITH COL2=COL2_MIN CONNECT BY NUMID-1=PRIOR NUMID
 GROUP BY COL1;
COL1       COL2
---------- ----------------------------------------
001        vl1,vl2,vl3
002        vl1,vl2

 
 方法三(需要知道确定有几行):
 SELECT deptno, dname, emps
  FROM (SELECT d.deptno, d.dname,
               RTRIM
                  (   e.ename
                   || ', '
                   || LEAD (e.ename, 1) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 2) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 3) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 4) OVER (PARTITION BY d.deptno ORDER BY e.ename)
                   || ', '
                   || LEAD (e.ename, 5) OVER (PARTITION BY d.deptno ORDER BY e.ename),
                   ', '
                  ) emps,
               ROW_NUMBER () OVER (PARTITION BY d.deptno ORDER BY e.ename) x
          FROM emp e, dept d
         WHERE d.deptno = e.deptno)
 WHERE x = 1
/
    DEPTNO DNAME          EMPS
---------- -------------- ----------------------------------------------------------------------
        10 ACCOUNTING     CLARK, KING, MILLER
        20 RESEARCH       ADAMS, FORD, JONES, SCOTT, SMITH
        30 SALES          ALLEN, BLAKE, JAMES, MARTIN, TURNER, WARD

--
we drink green tea

oracle 列去重相加

Oracle不同行的某列字符串相加,去除重复值

有如下表SRS_B_CW_TEST
City People Make
广州   1        A
广州   2        B
广州   3        C
上海   4        A
上海   5        E
广州   6        A
上海   7        E

实现如下效果
City People Make
上海   16     AE
广州   12     ABC

我们一步一步的学习

(1)如果直接group by则只能数字sum,字符串无法相加
select City,sum(People) as People from SRS_B_CW_TEST group by City order by City
实现效果如下
City  People
上海   16
广州   12

(2)下面的写法错误,加不上Make列
select City,sum(People) as People,Make from SRS_B_CW_TEST group by City order by City

(3)如果写成下面的sql语句
select City,sum(People) as People from SRS_B_CW_TEST group by City,Make order by City
实现效果如下
City  People
上海   4
上海   12
广州   7
广州   3
广州   2

(4)这时就可以加上Make列
select City,sum(People) as People,Make from SRS_B_CW_TEST group by City,Make order by City
实现效果如下
City People Make
上海   4       A
上海   12     E
广州   7       A
广州   3      B
广州   2      C

(5)下面想办法实现Make列的字符串相加

(6)构造树,sql语句如下
select City,People,Make,
       row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
from SRS_B_CW_TEST
实现效果如下
City  People  Make  RN   RM
上海    4         A      1    1
上海    5         E      2    2
上海    7         E      3    3
广州    6         A      4    1
广州    3         C      5    2
广州    2         B      6    3
广州    1         A      7    4

(7)有了树,就可以使用树型函数SYS_CONNECT_BY_PATH

(8)但是!如果按照(6)构造的树拼字符串的话会出问题,先写sql语句
select City,People,sys_connect_by_path(Make,',') as Make
from (
    select City,People,Make,
       row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
    from SRS_B_CW_TEST
)
start with RM=1
connect by prior RN=RN-1
实现效果如下
City  People  Make
上海    4       ,A
上海    5       ,A,E
上海    7       ,A,E,E
广州    6       ,A,E,E,A
广州    3       ,A,E,E,A,C
广州    2       ,A,E,E,A,C,B
广州    1       ,A,E,E,A,C,B,A
广州    6       ,A

只有7条数据,怎么多了1条,原来是RN没取好,不同组数字必须要'断开',导致connect by prior RN=RN-1处理时出了问题

(9)查找Oracle分析函数,我们发现一个函数对我们很有用rank(),于是我们修改6的sql语句
select City,People,Make,
       rank()over(order by City) + row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
from SRS_B_CW_TEST
实现效果如下
City  People  Make  RN   RM
上海    4         A     2     1
上海    5         E     3     2
上海    7         E     4     3
广州    6         A     8     1
广州    3         C     9     2
广州    2        B     10    3
广州    1        A     11    4

这样就'断开'了

(10)重写(8)的sql语句
select City,People,sys_connect_by_path(Make,',') as Make
from (
    select City,People,Make,
       rank()over(order by City) + row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
    from SRS_B_CW_TEST
)
start with RM=1
connect by prior RN=RN-1
实现效果如下
City  People  Make
上海    4       ,A
上海    5       ,A,E
上海    7       ,A,E,E
广州    6       ,A
广州    3       ,A,C
广州    2       ,A,C,B
广州    1       ,A,C,B,A

(11)目的快要实现了,下面用sum求和,max函数取出最大值
select City,sum(People) as People,max(sys_connect_by_path(Make,',')) as Make
from (
    select City,People,Make,
       rank()over(order by City) + row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
    from SRS_B_CW_TEST
)
start with RM=1
connect by prior RN=RN-1
group by
City
实现效果如下
City  People   Make
上海    16     ,A,E,E
广州    12     ,A,C,B,A

(12)去处第一个逗号,用ltrim函数
select City,sum(People) as People,ltrim(max(sys_connect_by_path(Make,',')),',') as Make
from (
    select City,People,Make,
       rank()over(order by City) + row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
    from SRS_B_CW_TEST
)
start with RM=1
connect by prior RN=RN-1
group by
City
实现效果如下
City  People   Make
上海    16     A,E,E
广州    12     A,C,B,A

(13)最后,去除重复的英文字母,这里需要借助函数的力量

(14)自己写一个函数
/************************************************************************************
创建者:曾浩
创建时间:2007-9-27
最新修改者:曾浩
最新修改时间:2007-9-27
用途:改进的split函数,
      实现这样的效果
      输入字符串123,123,234,345,234,345,456和字符串,
      输出123,234,345,456
************************************************************************************/
create or replace function ZH_SPLIT(v_string in varchar2, v_delimiter in varchar2)
    return varchar2
is
    j int:=0;
    i int:=1;
    len_string int:=0;
    len_delimiter int:=0;
    str varchar2(4000);
    v_return varchar2(4000);
begin
    len_string := LENGTH(v_string);
    len_delimiter := LENGTH(v_delimiter);
    while j < len_string
    loop
        j := INSTR(v_string, v_delimiter, i);
        if j = 0 then
            j := len_string;
            str := SUBSTR(v_string, i);
            if instr(v_return, str) > 0 then
                null;
            else
                v_return:=v_return||str||',';
            end if;
            if i >= len_string then
                exit;
            end if;
        else
            str := SUBSTR(v_string, i, j - i);
            i := j + len_delimiter;
            if instr(v_return, str) > 0 then
                null;
            else
                v_return:=v_return||str||',';
            end if;
        end if;
    end loop;
    v_return := substr(v_return, 1, length(v_return)-1);
    return v_return;
end;

(15)调用这个函数
select City,sum(People) as People,ZH_SPLIT(ltrim(max(sys_connect_by_path(Make,',')),','),',') as Make
from (
    select City,People,Make,
       rank()over(order by City) + row_number()over(order by City) RN,
       row_number()over(partition by City order by City) RM
    from SRS_B_CW_TEST
)
start with RM=1
connect by prior RN=RN-1
group by
City
实现效果如下
City  People   Make
上海    16     A,E
广州    12     A,C,B


--
we drink green tea