设为首页 收藏本站
查看: 848|回复: 0

[经验分享] Oracle 拼接列数据的方法

[复制链接]

尚未签到

发表于 2016-8-4 09:37:21 | 显示全部楼层 |阅读模式
  保存在这里,方便自己以后查看 (⊙_⊙) ╮(╯▽╰)╭
  
  我们可以先这样创建一张需要的临时表(Role 表):

select 'role_01' as role_id, 'admin' as role_category from dual
union all
select 'role_02' as role_id, 'admin' as role_category from dual
union all
select 'role_03' as role_id, 'normal' as role_category from dual
union all
select 'role_04' as role_id, 'normal' as role_category from dual
union all
select 'role_05' as role_id, 'normal' as role_category from dual
union all
select 'role_06' as role_id, 'normal' as role_category from dual
union all
select 'role_07' as role_id, 'normal' as role_category from dual
union all
select 'role_08' as role_id, 'normal' as role_category from dual
  
  表结构:

DSC0000.jpg
  
  现在我们要根据 role_category 分组,把相同 role_category 下的 role_id 连接起来,就是列 role_id 转成行,大家可能很容易想到使用 wm_concat() 方法来进行:

select role_category,
wm_concat(role_id) as role_id_list
from   (
select 'role_01' as role_id, 'admin' as role_category from dual
union all
select 'role_02' as role_id, 'admin' as role_category from dual
union all
select 'role_03' as role_id, 'normal' as role_category from dual
union all
select 'role_04' as role_id, 'normal' as role_category from dual
union all
select 'role_05' as role_id, 'normal' as role_category from dual
union all
select 'role_06' as role_id, 'normal' as role_category from dual
union all
select 'role_07' as role_id, 'normal' as role_category from dual
union all
select 'role_08' as role_id, 'normal' as role_category from dual
)
group by role_category
  
  好了,我们得到了查询结果:
DSC0001.jpg
  
  但是这个结果是否有点问题呢?
  我们发现第2行第2列的数据其 role_id 并不是按照从小到大排序的,似乎并不那么完美,得修改一下sql代码:

-- partition by role_category order by role_id 表示按照 role_category 分组,按照 role_id 排序
select role_category,   
wm_concat(role_id) over(partition by role_category order by role_id)   
as role_id_list   
from   (   
select 'role_01' as role_id, 'admin' as role_category from dual   
union all   
select 'role_02' as role_id, 'admin' as role_category from dual   
union all   
select 'role_03' as role_id, 'normal' as role_category from dual   
union all   
select 'role_04' as role_id, 'normal' as role_category from dual   
union all   
select 'role_05' as role_id, 'normal' as role_category from dual   
union all   
select 'role_06' as role_id, 'normal' as role_category from dual   
union all   
select 'role_07' as role_id, 'normal' as role_category from dual   
union all   
select 'role_08' as role_id, 'normal' as role_category from dual   
)
  
  现在的查询结果:
DSC0002.jpg
  
  这次的 role_id 都是排好序的,但是查询结果太多了,我们需要的只是最长的那一行数据,在 sql 中加一个 max() 方法就可以了:

select role_category,
max(role_id_list)
from   (
select role_category,
wm_concat(role_id) over(partition by role_category order by role_id)
as role_id_list
from   (
select 'role_01' as role_id, 'admin' as role_category from dual
union all
select 'role_02' as role_id, 'admin' as role_category from dual
union all
select 'role_03' as role_id, 'normal' as role_category from dual
union all
select 'role_04' as role_id, 'normal' as role_category from dual
union all
select 'role_05' as role_id, 'normal' as role_category from dual
union all
select 'role_06' as role_id, 'normal' as role_category from dual
union all
select 'role_07' as role_id, 'normal' as role_category from dual
union all
select 'role_08' as role_id, 'normal' as role_category from dual
)
)
group by role_category
   这次我们得到了想要的结果:
DSC0003.jpg
  
  但是为了得到这两条数据我们查出的数据多了点,而且又用了一次 max() 方法,这在效率上肯定是很低的
  wm_concat() 是系统函数,也许有的用户登录相关 Oracle 数据库得不到该函数的使用权限(比如我就是)
  下面再来看一种能够实现同样功能,但是不使用 wm_concat() 函数的方法。
  
  同样是使用最开始定义的那张临时表,我们先作一下查询,增加一列 row_number 用来记录 role_category 分组下的 role_id 序号,这里用到了系统函数 row_number():

select role_category,
role_id,
(row_number() over(partition by role_category order by role_id)) as row_number
from   (
select 'role_01' as role_id, 'admin' as role_category from dual
union all
select 'role_02' as role_id, 'admin' as role_category from dual
union all
select 'role_03' as role_id, 'normal' as role_category from dual
union all
select 'role_04' as role_id, 'normal' as role_category from dual
union all
select 'role_05' as role_id, 'normal' as role_category from dual
union all
select 'role_06' as role_id, 'normal' as role_category from dual
union all
select 'role_07' as role_id, 'normal' as role_category from dual
union all
select 'role_08' as role_id, 'normal' as role_category from dual
)
  
  查询结果:
DSC0004.jpg
  
  现在我们根据 row_number 把相同 role_category 的 role_id 用系统函数 sys_connect_by_path() 连接起来:

select role_category,
sys_connect_by_path(role_id, ',') as role_id_list
from   (
select role_category,
role_id,
(row_number() over(partition by role_category order by role_id))
as row_number
from   (
select 'role_01' as role_id ,'admin' as role_category from dual
union all
select 'role_02' as role_id ,'admin' as role_category from dual
union all
select 'role_03' as role_id ,'normal' as role_category from dual
union all
select 'role_04' as role_id ,'normal' as role_category from dual
union all
select 'role_05' as role_id ,'normal' as role_category from dual
union all
select 'role_06' as role_id ,'normal' as role_category from dual
union all
select 'role_07' as role_id ,'normal' as role_category from dual
union all
select 'role_08' as role_id ,'normal' as role_category from dual
)
)
where  connect_by_isleaf = 1
start with row_number = 1
connect by row_number - 1 = prior row_number
and role_category = prior role_category
   查询结果:
DSC0005.jpg
  
  开头多余了一个逗号,最后再用系统函数 ltrim() 来去掉这个逗号就OK了:

select role_category,
ltrim(sys_connect_by_path(role_id, ','), ',') as role_id_list
from   (
select role_category,
role_id,
(row_number() over(partition by role_category order by role_id))
as row_number
from   (
select 'role_01' as role_id ,'admin' as role_category from dual
union all
select 'role_02' as role_id ,'admin' as role_category from dual
union all
select 'role_03' as role_id ,'normal' as role_category from dual
union all
select 'role_04' as role_id ,'normal' as role_category from dual
union all
select 'role_05' as role_id ,'normal' as role_category from dual
union all
select 'role_06' as role_id ,'normal' as role_category from dual
union all
select 'role_07' as role_id ,'normal' as role_category from dual
union all
select 'role_08' as role_id ,'normal' as role_category from dual
)
)
where  connect_by_isleaf = 1
start with row_number = 1
connect by row_number - 1 = prior row_number
and role_category = prior role_category

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-252597-1-1.html 上篇帖子: oracle中常用函数大全(转) 下篇帖子: oracle常见的经典查询语句(二)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表