Oracle中的列值拼接函数listagg()

论坛 期权论坛 期权     
菜鸟张大海Flying   2019-7-21 04:28   4031   0
    最近在使用Oracle时碰到这种情况:一个公司的同一关联人存在多种关联关系,数据类似下表:


    为了便于分析,需要按不同公司将同一关联人的关联关系合并显示,如上表中赵一的“法人代表”和“股东”显示为一条记录,即实现“列转行”效果。
    这时,使用listagg()函数即可。
    一、数据准备:
    1.创建数据表
  1. create table tmp_20190720
复制代码
  1. (
复制代码
  1.   cust_num      VARCHAR2(20) not null,
复制代码
  1.   cust_name     VARCHAR2(30) not null,
复制代码
  1.   relative_name VARCHAR2(30) not null,
复制代码
  1.   relationship  VARCHAR2(30) not null
复制代码
  1. );
复制代码
   2.插入示例数据
  1. insert into tmp_20190720 values ('A001','公司1','赵一','法人代表');
复制代码
  1. insert into tmp_20190720 values ('A001','公司1','赵一','股东');
复制代码
  1. insert into tmp_20190720 values ('A002','公司2','孙二','法人代表');
复制代码
  1. insert into tmp_20190720 values ('A002','公司2','李四','股东');
复制代码
  1. insert into tmp_20190720 values ('A003','公司3','张三','实际控制人');
复制代码
  1. insert into tmp_20190720 values ('A003','公司3','张三','法人代表');
复制代码
  1. insert into tmp_20190720 values ('A003','公司3','张三','资本构成');
复制代码
    二、使用listagg()函数
    方法一:使用listagg() + group by 直接聚类
  1. select a.cust_num, a.cust_name, a.relative_name,
复制代码
  1.   listagg(a.relationship,'|') within group (order by a.relationship) relation_all
复制代码
  1. from tmp_20190720 a
复制代码
  1. group by a.cust_num, a.cust_name, a.relative_name
复制代码
  1. ;
复制代码
   代码解析:


    运行结果:


    方法二:使用listagg() + over (partition by ) 窗口函数
  1. select distinct a.cust_num, a.cust_name, a.relative_name,
复制代码
  1.   listagg(a.relationship,'|') within group (order by a.relationship)
复制代码
  1.     over (partition by a.cust_num, a.cust_name, a.relative_name) relation_all
复制代码
  1. from tmp_20190720 a
复制代码
  1. order by a.cust_num
复制代码
  1. ;
复制代码
   代码解析:


    运行结果:

    两种方法的运行效果一致。
    三、结束语
    还有一个函数wm_concat()能实现类似的效果,参考代码如下:
  1. select a.cust_num, a.cust_name, a.relative_name,
复制代码
  1.   wmsys.wm_concat(a.relationship) relation_all
复制代码
  1. from tmp_20190720 a
复制代码
  1. group by a.cust_num, a.cust_name, a.relative_name
复制代码
  1. ;
复制代码
   但是,Oracle 12c版本已经不推荐使用此函数,并且不作为内置函数。wm_concat()还有局限性,其不支持拼接字段排序,不能自定义分隔符(默认为逗号)。如确实需要在12c版本使用此函数,可以采用重写wm_concat()函数的方式,具体代码可在网络中方便的找到。例如,可参考文章:
  1. https://www.cnblogs.com/wangyong/p/6254872.html
复制代码
    以上,简要记录,防止遗忘。供参考。



分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP