Oracle行列转换

1.创建表

-- Create table
create table SHUJU1
(
  SUBJID      NVARCHAR2(20),
  VISIT       NVARCHAR2(50),
  FORM        NVARCHAR2(50),
  GOURPNAME   NVARCHAR2(50),
  DESCRIPTION NVARCHAR2(50),
  ITEM_VALUE  NVARCHAR2(100)
);
数据如下:

Oracle行列转换

2.转置后最终表如下:

-- Create table
create table 理化检查
(
  受试者编号          VARCHAR2(100),
  访视             VARCHAR2(100),
  表单             VARCHAR2(100),
  组别             VARCHAR2(100),
  红细胞数检测值        VARCHAR2(100),
  血红蛋白检测值        VARCHAR2(100),
  葡萄糖异常注释        VARCHAR2(100),
  红细胞检测值         VARCHAR2(100),
  白细胞临床判断        VARCHAR2(100),
  天门冬氨酸氨基转移酶异常注释 VARCHAR2(100),
  碱性磷酸酶临床判断      VARCHAR2(100),
  白细胞数检测值        VARCHAR2(100),
  血小板检测值         VARCHAR2(100),
  心电图结果          VARCHAR2(100),
  白细胞检测值         VARCHAR2(100),
  丙氨酸氨基转移酶检测值    VARCHAR2(100),
  谷氨酰转肽酶临床判断     VARCHAR2(100),
  心电图异常注释        VARCHAR2(100),
  血小板临床判断        VARCHAR2(100),
  丙氨酸氨基转移酶异常注释   VARCHAR2(100),
  红细胞数异常注释       VARCHAR2(100),
  血红蛋白临床判断       VARCHAR2(100),
  单位             VARCHAR2(100),
  白细胞数临床判断       VARCHAR2(100),
  血清总胆红素临床判断     VARCHAR2(100),
  血清总胆红素异常注释     VARCHAR2(100),
  白细胞异常注释        VARCHAR2(100),
  碱性磷酸酶异常注释      VARCHAR2(100),
  肌酐临床判断         VARCHAR2(100),
  检查日期           VARCHAR2(100),
  红细胞数临床判断       VARCHAR2(100),
  葡萄糖检测值         VARCHAR2(100),
  蛋白质临床判断        VARCHAR2(100),
  红细胞临床判断        VARCHAR2(100),
  红细胞异常注释        VARCHAR2(100),
  天门冬氨酸氨基转移酶临床判断 VARCHAR2(100),
  血小板异常注释        VARCHAR2(100),
  葡萄糖临床判断        VARCHAR2(100),
  心电图结论          VARCHAR2(100),
  蛋白质异常注释        VARCHAR2(100),
  肌酐异常注释         VARCHAR2(100),
  蛋白质检测值         VARCHAR2(100),
  天门冬氨酸氨基转移酶检测值  VARCHAR2(100),
  白细胞数异常注释       VARCHAR2(100),
  血红蛋白异常注释       VARCHAR2(100),
  碱性磷酸酶检测值       VARCHAR2(100),
  血清总胆红素检测值      VARCHAR2(100),
  谷氨酰转肽酶检测值      VARCHAR2(100),
  尿素氮检测值         VARCHAR2(100),
  尿素氮临床判断        VARCHAR2(100),
  尿素氮异常注释        VARCHAR2(100),
  心电图临床判断        VARCHAR2(100),
  丙氨酸氨基转移酶临床判断   VARCHAR2(100),
  谷氨酰转肽酶异常注释     VARCHAR2(100),
  肌酐检测值          VARCHAR2(100)
);
Oracle行列转换

3.实现的存储过程如下:

CREATE OR REPLACE PROCEDURE OC Authid Current_User IS
  --存放插入数据的SQL
  LV_SQL VARCHAR2(6000);
  --存放创建表的SQL
  SQL_COMMOND VARCHAR2(5000);
  CREAT_TABLE VARCHAR2(100);
  CREAT_TABLE1 VARCHAR2(200);
  CREAT_TABLE2 VARCHAR2(4000);
  CREAT_TABLE3 VARCHAR2(9000);
  CREAT_TABLE4 VARCHAR2(100);
  --定义游标
  CURSOR CUR IS
   select distinct DESCRIPTION,FORM from shuju1;
    
BEGIN
  --定义查询开头
  SQL_COMMOND := 'SELECT SUBJID,VISIT,FORM,GOURPNAME ';
  CREAT_TABLE := 'create table ';
  CREAT_TABLE1 :='';
  CREAT_TABLE2 :='';
  CREAT_TABLE3 :='';
  CREAT_TABLE4 :='';
  FOR I IN CUR
  LOOP
    --将结果相连接
    SQL_COMMOND := SQL_COMMOND || ' ,wmsys.wm_concat(to_char(DECODE(DESCRIPTION,''' || replace(I.DESCRIPTION,':','') ||
                   ''',ITEM_VALUE,''''))) ' || replace(I.DESCRIPTION,':','');
    CREAT_TABLE1 :=  I.FORM || '  (受试者编号  VARCHAR2(100),访视  VARCHAR2(100),表单  VARCHAR2(100),组别 VARCHAR2(100),';
    CREAT_TABLE2 := CREAT_TABLE2 || replace(I.DESCRIPTION,':','') || ' VARCHAR2(100),';
    CREAT_TABLE4 :=  I.FORM || ' ';
  END LOOP;
 -- CLOSE CUR;
 
  CREAT_TABLE2 := RTRIM(CREAT_TABLE2,',');
  CREAT_TABLE3 := CREAT_TABLE || CREAT_TABLE1 || CREAT_TABLE2 || ')';
  
  --pDsp(SQL_COMMOND);
 -- pDsp(replace(SQL_COMMOND,chr(13)||chr(10),''''));
 -- pDsp(SQL_COMMOND);
  
  EXECUTE IMMEDIATE CREAT_TABLE3;
  commit;
 
  --pDsp(LV_SQL);
  --pDsp(CREAT_TABLE3);


  
  SQL_COMMOND := SQL_COMMOND || ' from shuju1 group by SUBJID,VISIT,FORM,GOURPNAME';
  LV_SQL := 'INSERT INTO ' || CREAT_TABLE4  || SQL_COMMOND;
  
  -- pDsp(LV_SQL);
  EXECUTE IMMEDIATE LV_SQL;
  --pDsp(LV_SQL);
  commit;

  
  EXCEPTION
    WHEN OTHERS THEN
     ROLLBACK;
     NULL;

END OC;
---------------------------------------------------------------------------------------------------------------------

其中打印长值的函数如下(会自动添加回车和换行):

create or replace procedure pDsp(str varchar2) is

begin
  if length(str) > 80 then
      dbms_output.put_line(substr(str, 1, 80));
      pDsp(substr(str, 81));
  else
      dbms_output.put_line(str);
  end if;

exception
  when others then
      dbms_output.enable(1000000);
      pDsp(str);
end pDsp;
删除回车和换行的方法:

Oracle行列转换

Oracle行列转换

注意事项:(1)若description列有特殊字符,则必须删除:可用replace函数;(2)若description列有空列要删除,否则创建表不成功。