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