您的位置:首页 > 数据库 > Oracle

oracle sql分组合并

2015-08-15 13:34 691 查看
Sql代码

create table TABLE1
(
ID   INTEGER,
NAME VARCHAR2(10)
)

create table TABLE2
(
ID   INTEGER,
ROLE VARCHAR2(10)
)

insert into TABLE1 (ID, NAME) values (1, '张三');
insert into TABLE1 (ID, NAME) values (2, '李四');
commit;

insert into TABLE2 (ID, ROLE) values (1, '查询');
insert into TABLE2 (ID, ROLE) values (1, '分析');
insert into TABLE2 (ID, ROLE) values (1, '决策');
insert into TABLE2 (ID, ROLE) values (2, '查询');
commit;
create table TABLE1( ID INTEGER, NAME VARCHAR2(10))create table TABLE2( ID INTEGER, ROLE VARCHAR2(10))insert into TABLE1 (ID, NAME) values (1, '张三');insert into TABLE1 (ID, NAME) values (2, '李四');commit;insert into TABLE2 (ID, ROLE) values (1, '查询');insert into TABLE2 (ID, ROLE) values (1, '分析');insert into TABLE2 (ID, ROLE) values (1, '决策');insert into TABLE2 (ID, ROLE) values (2, '查询');commit;

要求输出结果:

Sql代码

ID  NAME    ROLE
1    张三 查询,分析,决策
2    李四 查询
ID NAME ROLE1 张三 查询,分析,决策2 李四 查询

方法一、使用wmsys.wm_concat

Sql代码

select table1.*,wmsys.wm_concat(role) from table1,table2 where table1.id=table2.id  group by table1.id,table1.name

方法二、使用sys_connect_by_path

Sql代码

select id, name, ltrim(max(sys_connect_by_path(role, ',')), ',') from
(select row_number() over(partition by table1.id order by name) rn,table1.*, role from table1, table2  where table1.id =

table2.id)
start with rn = 1
connect by prior rn = rn - 1 and prior id = id
group by id, name
order by id

select id, name, ltrim(max(sys_connect_by_path(role, ',')), ',') from (select row_number() over(partition by table1.id order by name) rn,table1.*, role from table1, table2 where table1.id = table2.id)start with rn = 1connect by prior rn = rn - 1 and prior id = idgroup by id, nameorder by id

例如有如下数据:
000297                                    chenpeng
000297                                    liusu
合并处理后需显示为:
000297                                    chenpeng,liusu

网上查了很多方法,但通常而言都是编写自定义多行文本合并函数,或者对支持的列数具有局限性。
最后在英文google中搜到如下比较巧的方法。不用在数据库中增加function,纯SQL一次性搞定,
而且扩充性很好,没有列的限制。
主要SQL如下:

SELECT   n_sec_code, TRANSLATE (LTRIM (text, '/'), '*/', '*,') researcherList
FROM (SELECT ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code,
lvl DESC) rn,
n_sec_code, text
FROM (SELECT     n_sec_code, LEVEL lvl,
SYS_CONNECT_BY_PATH (c_researcher_code,'/') text
FROM (SELECT   n_sec_code, c_researcher_code as c_researcher_code,
ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code,c_researcher_code) x
FROM m_researcher_stock_rel
ORDER BY n_sec_code, c_researcher_code) a
CONNECT BY n_sec_code = PRIOR n_sec_code AND x - 1 = PRIOR x))
WHERE rn = 1
ORDER BY n_sec_code;

预想的结果成功出现,多行数据成功汇总到一行,特此分享与大家。对于你自己的应用中,只需要把SQL中“n_sec_code”
换为你的用来汇总的列,“c_researcher_code”替换为需合并文本的列,“m_researcher_stock_rel”替换为你的表名,就是这么简单。

SQL分析:
1、利用 “ROW_NUMBER () OVER (PARTITION BY……” 为按“股票代码”汇总后的数据行添加组内序号
2、“SYS_CONNECT_BY_PATH”  按组内序号相邻关系,为每一层进行不同行的“研究员代码”叠加
3、再次利用“股票代码”进行组内分组,但按第二部中的层次排倒序,增加调整后等级
4、取所有调整后等级为1的结果,即为所要求的数据行

文章来自学IT网:http://www.xueit.com/html/2009-07/25_4207_00.html

方法三、使用自定义函数

Sql代码 ORACLE 分组多行合并一行 - winner - 宇宙的尽头的博客

create or replace function my_concat(mid in integer) return varchar2       --记住:参数和返回值里的数据类型都不用定义长度
is
result varchar2(4000);    --定义变量,记住Oracle中定义变量不需要
begin
for temp_cursor in (select role from table2 where id=mid) loop     --此处在游标FOR循环中使用查询
result :=result || temp_cursor.role || ',';    --Oracle中字符连接使用||,而sql server中用+
end loop;
result := rtrim(result,',');  --去掉最后一个空格,还有Oracle中的赋值前面没有set
return result;
end;

select table1.*,my_concat(table1.id) from table1,table2 where table1.id=table2.id
group by table1.id,table1.name
order by table1.id
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: