现在的位置: 首页 > 综合 > 正文

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

2013年05月05日 ⁄ 综合 ⁄ 共 4830字 ⁄ 字号 评论关闭

有如下表SRS_B_CW_TESTCity 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) RMfrom 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 Makefrom (    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=1connect 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) RMfrom 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 Makefrom (    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=1connect 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 Makefrom (    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=1connect by prior RN=RN-1group byCity实现效果如下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 Makefrom (    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=1connect by prior RN=RN-1group byCity实现效果如下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 varchar2is   
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 Makefrom (    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=1connect by prior RN=RN-1group byCity实现效果如下City 
People   Make上海    16     A,E广州    12     A,C,B

(16)大功告成!

抱歉!评论已关闭.