Oracle 函数 wm_concat 将列转行 用法 实例

Oracle 函数 wm_concat 将列转行 用法 实例

        这篇文章主要记录下我工作中遇到sql语句查询的问题,工作中有个需求是做问卷调查,然后统计导出数据,其中有个问题是多选题,存的是答案表对应的答案的id(以逗号分隔),然后查询的时候怎么样才能把这个问题的答案也查出来拼接成逗号分隔,就用到了 WM_CONCAT 函数,下面就说一下具体用法。

      1. 首先看一下我的表结构,总共 有三张表 ,qv_question 记录了问题,qv_answer 记录了 问题对应的答案(单选,多选的选项,而不是调查回答的答案),qv_investreplay 这个记录了每个人 问卷调查 回答的 问题对应的答案,因此 一个人回答了多个问题,一个问题有多个答案,qv_investreplay 对qv_question 是一对多,同样 qv_question 对 qv_answer 也是一对多

       Oracle 函数 wm_concat 将列转行 用法 实例

Oracle 函数 wm_concat 将列转行 用法 实例

— Create table
create table QV_QUESTION
(
  id            VARCHAR2(32) not null,
  questionorder NUMBER,
  questionname  VARCHAR2(300),
  questiontype  VARCHAR2(1),
  investid      VARCHAR2(32),
  addusername   VARCHAR2(50),
  addtime       DATE,
  adddept       VARCHAR2(200),
  addname       VARCHAR2(50),
  isdeleted     VARCHAR2(50),
  investname    VARCHAR2(200),
  allowwrite    VARCHAR2(50)
)
tablespace RMSFUSION
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64
    minextents 1
    maxextents unlimited
  );
— Add comments to the table
comment on table QV_QUESTION
  is ‘题目表’;
— Add comments to the columns
comment on column QV_QUESTION.questionorder
  is ‘题目排序’;
comment on column QV_QUESTION.questionname
  is ‘题目名称’;
comment on column QV_QUESTION.questiontype
  is ‘类型 1 :单选2:复选  3:文本框’;
comment on column QV_QUESTION.investid
  is ‘主题id’;
comment on column QV_QUESTION.isdeleted
  is ‘0:未删除 1:删除’;
comment on column QV_QUESTION.investname
  is ‘主题名称’;
comment on column QV_QUESTION.allowwrite
  is ‘如果是单选复选的话是否允许客户手动输入 0:不允许1允许’;
— Create/Recreate primary, unique and foreign key constraints
alter table QV_QUESTION
  add constraint PK_QV_QUESTION primary key (ID)
  using index
  tablespace RMSFUSION
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
Oracle 函数 wm_concat 将列转行 用法 实例

Oracle 函数 wm_concat 将列转行 用法 实例

— Create table
create table QV_ANSWER
(
  id           VARCHAR2(32) not null,
  answername   VARCHAR2(200),
  questionid   VARCHAR2(3200),
  addusername  VARCHAR2(50),
  addtime      DATE,
  adddept      VARCHAR2(200),
  addname      VARCHAR2(50),
  isdeleted    VARCHAR2(50),
  questionname VARCHAR2(200),
  ordernumber  NUMBER
)
tablespace RMSFUSION
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64
    minextents 1
    maxextents unlimited
  );
— Add comments to the table
comment on table QV_ANSWER
  is ‘问题答案表’;
— Add comments to the columns
comment on column QV_ANSWER.answername
  is ‘答案名称’;
comment on column QV_ANSWER.questionid
  is ‘题目id’;
comment on column QV_ANSWER.isdeleted
  is ‘0:未删除  1:已删除’;
comment on column QV_ANSWER.questionname
  is ‘题目名称’;
comment on column QV_ANSWER.ordernumber
  is ‘答案排序’;
— Create/Recreate primary, unique and foreign key constraints
alter table QV_ANSWER
  add constraint PK_QV_ANSWER primary key (ID)
  using index
  tablespace RMSFUSION
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );

Oracle 函数 wm_concat 将列转行 用法 实例

Oracle 函数 wm_concat 将列转行 用法 实例

— Create table

create table QV_INVESTREPLAY

(

  id          VARCHAR2(32) not null,

  investid    VARCHAR2(32),

  questionid  VARCHAR2(32),

  answerid    VARCHAR2(255),

  useranswer  VARCHAR2(500),

  addusername VARCHAR2(50),

  addtime     DATE,

  adddept     VARCHAR2(200),

  addname     VARCHAR2(50),

  isreplay    VARCHAR2(30),

  allowanswer VARCHAR2(255)

)

tablespace RMSFUSION

  pctfree 10

  initrans 1

  maxtrans 255

  storage

  (

    initial 64

    minextents 1

    maxextents unlimited

  );

— Add comments to the table

comment on table QV_INVESTREPLAY

  is ‘问卷反馈表’;

— Add comments to the columns

comment on column QV_INVESTREPLAY.investid

  is ‘问卷id’;

comment on column QV_INVESTREPLAY.questionid

  is ‘题目id’;

comment on column QV_INVESTREPLAY.answerid

  is ‘答案id’;

comment on column QV_INVESTREPLAY.useranswer

  is ‘用户答案(文本框)’;

comment on column QV_INVESTREPLAY.addusername

  is ‘参与者工号’;

comment on column QV_INVESTREPLAY.addtime

  is ‘参与时间’;

comment on column QV_INVESTREPLAY.adddept

  is ‘参与者部门’;

comment on column QV_INVESTREPLAY.addname

  is ‘参与者姓名’;

comment on column QV_INVESTREPLAY.isreplay

  is ‘是否已经回复 0:未回复 1:已回复’;

comment on column QV_INVESTREPLAY.allowanswer

  is ‘单选多选题客户补充答案’;

— Create/Recreate primary, unique and foreign key constraints

alter table QV_INVESTREPLAY

  add constraint PK_QV_INVESTREPLAY primary key (ID)

  using index

  tablespace RMSFUSION

  pctfree 10

  initrans 2

  maxtrans 255

  storage

  (

    initial 64K

    minextents 1

    maxextents unlimited

  );

      2. 这里只看 有个多选题, “你希望影吧播放的电影类型是?”,以及这个问题的答案。

           Oracle 函数 wm_concat 将列转行 用法 实例

           Oracle 函数 wm_concat 将列转行 用法 实例

         这是问卷调查 回答的答案,可以看到,存的 都是 qv_answer 表对应的 id,并且以 逗号分隔

            Oracle 函数 wm_concat 将列转行 用法 实例

     3. 如何用 wm_concat 函数 查出下列结果,sql 语句 如下:

        select a.id,a.addusername,a.addname,a.adddept,a.addtime,to_char(WM_CONCAT(b.answername)) 类型
                      from qv_investreplay a,qv_answer b
                              where  b.questionid = ‘422517’ and  instr(‘,’||a.answerid||’,’,’,’||b.id||’,’)>0
                                     group by a.id,a.addusername,a.addname,a.adddept,a.addtime

          Oracle 函数 wm_concat 将列转行 用法 实例

        关联条件 使用 instr(‘,’||a.answerid||’,’,’,’||b.id||’,’)>0,这样就可以关联出所有 id 对应的答案,这时候 使用 to_char(WM_CONCAT(b.answername)) 类型 将答案以逗号拼接,其他查询字段,都要在 group by 里。

        也可以用with as 做临时表 an (qv_investreplay 也可以写一个with as,只把相关字段写出来,便于测试),简单写下 如下:

              with an
                   as (
                          select id,answername from qv_answer where questionid = ‘422517’
                    )
             select a.id,a.addusername,a.addname,a.adddept,a.addtime,to_char(WM_CONCAT(b.answername)) 类型
                      from qv_investreplay a,an b
                                where instr(‘,’||a.answerid||’,’,’,’||b.id||’,’)>0
                                      group by a.id,a.addusername,a.addname,a.adddept,a.addtime

      3. 有时安装的 oracle 可能版本 并没有 wm_concat 函数,这时可以自定义,如下sql语句:

          Oracle 11gR2和12C上已经摒弃了wm_concat函数,当时我们很多程序员在程序中确使用了该函数,导致程序出现错误,为了减轻程序员修改程序的工作量,只有通过手工创建个wm_concat函数,来临时解决该问题,但是注意,及时创建了该函数,在使用的过程中,也需要用to_char(wm_concat())方式,才能完全替代之前的应用。

一.解锁wmsys用户
alter user wmsys account unlock;

二.创建包、包体和函数
以wmsys用户登录数据库,执行下面的命令

CREATE OR REPLACE TYPE WM_CONCAT_IMPL AS OBJECT
— AUTHID CURRENT_USER AS OBJECT
(
CURR_STR VARCHAR2(32767),
STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT WM_CONCAT_IMPL) RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT WM_CONCAT_IMPL,
P1 IN VARCHAR2) RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN WM_CONCAT_IMPL,
RETURNVALUE OUT VARCHAR2,
FLAGS IN NUMBER)
RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT WM_CONCAT_IMPL,
SCTX2 IN WM_CONCAT_IMPL) RETURN NUMBER
);
/

–定义类型body:
CREATE OR REPLACE TYPE BODY WM_CONCAT_IMPL
IS
STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT WM_CONCAT_IMPL)
RETURN NUMBER
IS
BEGIN
SCTX := WM_CONCAT_IMPL(NULL) ;
RETURN ODCICONST.SUCCESS;
END;
MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT WM_CONCAT_IMPL,
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 WM_CONCAT_IMPL,
RETURNVALUE OUT VARCHAR2,
FLAGS IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURNVALUE := CURR_STR ;
RETURN ODCICONST.SUCCESS;
END;
MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT WM_CONCAT_IMPL,
SCTX2 IN WM_CONCAT_IMPL)
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 wm_concat(P1 VARCHAR2)
RETURN VARCHAR2 AGGREGATE USING WM_CONCAT_IMPL ;
/

三.创建同义词并授权

create public synonym WM_CONCAT_IMPL for wmsys.WM_CONCAT_IMPL
/
create public synonym wm_concat for wmsys.wm_concat
/

grant execute on WM_CONCAT_IMPL to public
/
grant execute on wm_concat to public
/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111327.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java实现http协议_java用http协议本地文件

    java实现http协议_java用http协议本地文件对于那些感兴趣的人,这是一个片段.我能够通过FluxLauncher而不是reactor-nettyUDP类来实现.privatestaticfinalStringSSDP_IP=”239.255.255.250″;privatestaticfinalintSSDP_PORT=1900;privatestaticfinalintTIMEOUT=500…

    2022年10月11日
  • 小米bl未解锁变砖了如何刷机_如何安装MIUI 10[通俗易懂]

    小米bl未解锁变砖了如何刷机_如何安装MIUI 10[通俗易懂]MIUI,一个安卓系统,如何安装?先说一下,MIUI10目前支持这些小米手机/平板:手机:小米4、红米3S、红米3X、红米Note3、小米4c、红米Pro、红米Note4、小米4S、红米5A、小米5、红米5Plus、小米6、小米Note2、红米6Pro、红米Note5、小米Max2、小米MIX、小米Max、小米MIX2S、小米5X、红米4、小米6X、红米Note5A、红米4A、…

    2022年5月9日
  • nexus3下载地址

    nexus3下载地址由于nexus目前官网上已经很难下载了,除非翻墙,故整理了一下目前最新版本的分享一下,有需要的欢迎下载。win64:nexus-3.20.1-01-win64.zip链接:https://pan.baidu.com/s/19THgVb6LzLXJlxzomsvwhw提取码:9vvglinux:nexus-3.20.1-01-unix.tar.gz链接:https://pan.baid…

    2022年7月12日
  • linux下进程的管理_LINUX教程

    linux下进程的管理_LINUX教程作者:RodmaChen关注我的csdn博客,更多Linux笔记知识还在更新本人只在csdn写博客Linux进程管理一.什么是进程和程序二.查看进程——ps,top,pstree三.进程的启动方式四.进程的控制五.实训任务一.什么是进程和程序进程:开始执行但是还没有结束的程序的实例程序:包含可执行代码的文件进程与程序的关系进程由程序产生,是一个运行着的、要占系统资源的程序进程不等于程序进程与程序是多对一进程是占用(消耗)系统资源的二.查看进程—.

    2022年9月10日
  • Depix 这款去“马赛克“工具效果如何?

    Depix 这款去“马赛克“工具效果如何?最近突然冒出一则新闻,说出了一款开源去“马赛克“工具,三天获Github5000星,火爆网络!这款工具就是depix。出于好奇,去github下载了,文件很小,压缩包才580k,解压后也不到700k,里面的文件是python语言写的,主目录下就一个文件:depix.py,主目录下包含三个目录depixlib(库文件),docs(文档),images(需要用到的图片),如下图:根据depix在github上介绍,该文件目的根本不是去马赛克,而是做密码恢复使用,是对于手机或其他截屏上的类似马赛克

    2022年6月26日
  • OPC协议_opc通讯协议简介

    OPC协议_opc通讯协议简介一、OPC:OPC是一种利用微软的COM/DCOM技术来达成自动化控制的协定,采用典型的C/S模式,针对硬件设备的驱动程序由硬件厂商完成,提供统一OPC接口标准的Server程序,软件厂商只需按照OPC标准接口编写Client程序就访问Server程序进行读写,即可实现与硬件设备的通信。OPC协定包括:1.DA(DataAccess)规范:访问数据主要采用该规范2.A&E(Alarma…

    2022年10月22日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号