oracle的wm_concat函数实现行转列

有以下数据

deptname phone username isboss
部门A 电话1 员工A 0
部门A 电话1 领导A 1
部门B 电话2 员工B 0
部门B 电话2 员工C 0
部门B 电话2 领导D 1

需要展示效果

deptname phone boss emp
部门A 电话1 领导A 员工A
部门B 电话2 领导D 员工B,员工C

因为是oracle10g的原因,所以使用了wm_concat函数,但对wm_concat结果长度有限制,超出会报ORA-22922:不存在的LOB值,这是后话,先贴代码

Select t5.deptname,
       Max(t5.tel),
       dbms_lob.substr(wmsys.wm_concat(To_Char(t5.boss))) boss,
       dbms_lob.substr(wmsys.wm_concat(To_Char(t5.notboss))) notboss
  From (Select t1.NAME deptname,
               t1.TEL tel,
               Case t2.ISBOSS
                 When 1 Then
                  t2.TRUE_NAME
               End boss,
               Case t2.ISBOSS
                 When 0 Then
                  t2.TRUE_NAME
               End notboss
          From t_duty t
          Left Join t_department t1
            On t.DEP_ID = t1.DEP_ID
          Left Join t_contacts t2
            On t.CONTACTS_ID = t2.CONTACTS_ID
         Where t.DUTY_TIME = Trunc(SysDate) ) t5
 Group By t5.deptname

同样的情况的如果是oracle11gR2版本可以用LISTAGG函数,据说可以解决上面的报错问题,这个有待以后测试

但是我现在的是10g的,而且会报上面的错误,网上的一些解决方案都没解决,有人写了自定义函数,亲测完美解决

原出处已经找不到了,就不贴链接了,但还是非常感谢解决了这个问题

create or replace TYPE zh_concat_im
AUTHID CURRENT_USER AS OBJECT
(
  CURR_STR VARCHAR2(32767),
  STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT zh_concat_im) RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT zh_concat_im,
               P1 IN VARCHAR2) RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN zh_concat_im,
                                 RETURNVALUE OUT VARCHAR2,
                                 FLAGS IN NUMBER)
                     RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT zh_concat_im,
                    SCTX2 IN  zh_concat_im) RETURN NUMBER
);
/
create or replace TYPE BODY zh_concat_im
IS
  STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT zh_concat_im)
  RETURN NUMBER
  IS
  BEGIN
    SCTX := zh_concat_im(NULL) ;
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT zh_concat_im,
          P1 IN VARCHAR2)
  RETURN NUMBER
  IS
  BEGIN
    IF(CURR_STR IS NOT NULL) THEN
      CURR_STR := CURR_STR || ‘:‘ || P1;
    ELSE
      CURR_STR := P1;
    END IF;
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN zh_concat_im,
                                 RETURNVALUE OUT VARCHAR2,
                                 FLAGS IN NUMBER)
    RETURN NUMBER
  IS
  BEGIN
    RETURNVALUE := CURR_STR ;
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT zh_concat_im,
                                   SCTX2 IN zh_concat_im)
  RETURN NUMBER
  IS
  BEGIN
    IF(SCTX2.CURR_STR IS NOT NULL) THEN
      SELF.CURR_STR := SELF.CURR_STR || ‘:‘ || SCTX2.CURR_STR ;
    END IF;
    RETURN ODCICONST.SUCCESS;
  END;
END;
/
create or replace FUNCTION zh_concat(P1 VARCHAR2)
RETURN VARCHAR2 AGGREGATE USING zh_concat_im ;
/
时间: 2024-12-23 21:51:18

oracle的wm_concat函数实现行转列的相关文章

Oracle 11g Pivot函数实现行转列

先上语法规范: SELECT .... FROM <table-expr> PIVOT ( aggregate-function(<column>) FOR <pivot-column> IN (<value1>, <value2>,..., <valuen>) ) AS <alias> WHERE ..... 通过一个例子说明其用法: select * from (select salary, department_id

用decode函数实现行变列

用decode函数实现行变列----创建测试表create table student_score(name varchar2(20),subject varchar2(20),score number(4,1));-----插入测试数据insert into student_score (name,subject,score)values('张三','语文',78);insert into student_score (name,subject,score)values('张三','数学',8

重写Oracle的wm_concat函数,自定义分隔符、排序

oracle中,wm_concat函数是一个聚合函数,和mysql中的group_concat函数类似,不过group_concat函数比较强大,可以定义分隔符和排序,当然所谓强大是相对的,这里假使我们不知道oracle中的over函数,也不知道listagg函数. 我们先来看看wm_concat函数能实现什么功能,通俗点==>列传行,如果不明白,请看下面截图(可以看到分隔符默认为','顺序也是杂乱的)          所以,接下来,我们开始重写wm_concat函数(需要注意和需要说明的地方

oracle的神奇化学反应(行转列+获取表字段)

橘子+汽水=橘子汽水,∑(?Д?ノ)ノ好无聊!!! 火鸡+烤架=烤火鸡,?(´?`?)还不错. wm_concat()+表字段查询=(?ω?)会是啥呢? wm_concat()函数,该函数可以把列值以","号分隔,并显示成一行.例子如下: 我有一个超级大的美食表CHINA_FOODS,里面包含了全国各地的美食,从地锅鸡.羊盘肠到红烧肉.臭豆腐... 今天加班写博客,写到这里的时候我感觉肥肠的饿,想点个外卖,于是想从美食表里面找个好吃的下单: 为了节省时间来写博客,我决定把下单和付款的重

Oracle没有WM_CONCAT函数的解决办法

WM_CONCAT是oracle的非公开函数,并不鼓励使用,新版本oracle并没有带此函数,需要手工加上. 1.下载三个文件:owmctab.plb  . owmaggrs.plb . owmaggrb.plb 2.用sqlplus登录:sqlplus -logon sys/123 as sysdba 3.执行@C:\Users\JOYTRAVEL\Desktop\WMSYS用户\owmaggrb.plb; 如果执行结果报错,说找不到WMSYS用户,那么执行 @C:\Users\JOYTRAV

Oracle行转列操作

有时候我们在展示表中数据的时候,需要将行转为列来显示,如以下形式: 原表结构展示如下:---------------------------产品名称    销售额     季度---------------------------奶酪          50     第一季度奶酪          60     第二季度啤酒          50     第二季度啤酒          80     第四季度--------------------------- 现在需要将上面的原表结构转换为

sql与oracle中有关case和decode的用法(行转列)及比较(转

引: 为了举例说明,这里创建了一张成绩表,如下图所示: 比较: 1.sql中,这两个函数我们仅能使用case,代码及结果如下: select name,       case Subject          when '语文' then 1          when '数学' then 2          when '英语' then 3   --else 3       end  as '科目代码'   from Results 同样的,我们可以用case实现行转列,代码及结果如下: s

PIVOT:行转列函数

PIVOT函数,行转列 PIVOT函数的格式如下: PIVOT(<聚合函数>([聚合列值]) FOR [行转列前的列名] IN([行转列后的列名1],[行转列后的列名2],[行转列后的列名3],.......[行转列后的列名N]))<聚合函数>就是我们使用的SUM,COUNT,AVG等Sql聚合函数,也就是行转列后计算列的聚合方式.[聚合列值]要进行聚合的列名[行转列前的列名]这个就是需要将行转换为列的列名.[行转列后的列名]这里需要声明将行的值转换为列后的列名,因为转换后的列名其

SqlServer PIVOT函数快速实现行转列,UNPIVOT实现列转行

来自于 https://www.cnblogs.com/OpenCoder/p/6668882.html 我们在写Sql语句的时候没经常会遇到将查询结果行转列,列转行的需求,拼接sql字符串,然后使用sp_executesql执行sql字符串是比较常规的一种做法.但是这样做实现起来非常复杂,而在SqlServer2005中我们有了PIVOT/UNPIVOT函数可以快速实现行转列和列转行的操作. PIVOT函数,行转列 PIVOT函数的格式如下 PIVOT(<聚合函数>([聚合列值]) FOR