DB2 中的动态数据透视 SQL 查询

如何解决DB2 中的动态数据透视 SQL 查询

我在 DB2 中有如下表,其中所有这 3 列都是 VARCHAR 数据类型

DATE_F    FILE_NM   ROW_ID  COLUMN_NM   COLUMN_VAL 
20200131  ABC.TXT     1      ABC_COL1     123
20200131  ABC.TXT     1      ABC_COL2     XYZ
20201231  ABC.TXT     2      ABC_COL1     456
20201231  ABC.TXT     2      ABC_COL2     XY1
20200630  XYZ.TXT     1      XYZ_COL1     PQR
20200630  XYZ.TXT     1      XYZ_COL2     567
20200630  XYZ.TXT     1      XYZ_COL3     MNO

我需要一个动态 PIVOT 查询,当 FILE_NM 过滤器用作 ABC.TXT 时,它应该以行格式选择 ABC_COL1 和 ABC_COL2 的值

当 FILE_NM 过滤器用作 XYZ.TXT 时,相同的查询应以行格式选择 XYZ_COL1、XYZ_COL2 和 XYZ_COL3 的值

当 FILE_NM=ABC.TXT 时输出应该如下图

DATE_F    ROW_ID   ABC_COL1   ABC_COL2    
20200131    1        123       XYZ
20201231    2        456       XY1

当 FILE_NM=XYZ.TXT 时输出应该如下图

 DATE_F    ROW_ID     XYZ_COL1     XYZ_COL2     XYZ_COL3
20200630    1           PQR         567           MNO

因此,一一查询就能提取数据。在这种情况下,任何函数或等效函数都可以完成任务吗?

解决方法

您可以尝试使用以下通用存储过程进行透视。

--#SET TERMINATOR @
create or replace procedure pivot
(
  in  sel_stmt varchar(4000),in  row_cols varchar(200),in  col_col  varchar(128),in  agg_col  varchar(128),in  agg_fn   varchar(10),in  tmp_tbl  varchar(128),in  null_ind varchar(10),out rc       int,out msg      varchar(128),out stmt     varchar(4000)
)
LANGUAGE SQL
DYNAMIC RESULT sets 1
BEGIN
 declare QUOT1        char(1) default '''';
 declare QUOT2        char(1) default '"';
 declare SQLCODE      int default 0;
 declare SQLTYPE_ID   int;
 declare SQLTYPE      varchar(128);
 declare SQLLENGTH    int;
 declare SQLSCALE     int;
 declare SQLNAME_DATA varchar(128);
 declare SQLTYPEF     varchar(128);
 declare col_val      varchar(4000);
 declare apo          varchar(1);
 declare l1 RESULT_set_LOCATOR VARYING;

 declare c2 cursor for s2;
 declare c_out cursor with return for s_out;

 declare EXIT HANDLER FOR SQLEXCEPTION
 BEGIN
   GET DIAGNOSTICS EXCEPTION 1 MSG = MESSAGE_TEXT;
   set RC = SQLCODE;
 END;

 set col_col=upper(col_col);
 set agg_col=upper(agg_col);
 -- insert result of select statement into temp table
 set stmt = 'describe '||sel_stmt;
 call SYSPROC.ADMIN_CMD(stmt);
 set stmt = '';
 associate result set locator (l1)
 with procedure SYSPROC.ADMIN_CMD;
 allocate c1 cursor for result set l1;
 --open c1;
 fetch c1 into SQLTYPE_ID,SQLTYPE,SQLLENGTH,SQLSCALE,SQLNAME_DATA;
 while (SQLCODE!=100) do
   set SQLTYPEF = SQLTYPE
   ||case 
      when SQLTYPE IN ('DECIMAL','DECFLOAT','CHARACTER','VARCHAR') then 
         '('||RTRIM(CHAR(SQLLENGTH))
       ||case when SQLTYPE='DECIMAL' then ','||RTRIM(CHAR(SQLSCALE)) else '' end
       ||')'                                
      else ''
     end;
   if (col_col=SQLNAME_DATA) then
     set apo = 
      case 
       when SQLTYPE in ('DECIMAL','INTEGER','SMALLINT','BIGINT','REAL','DOUBLE') then '' 
       else QUOT1 
      end;
   end if;
   set stmt = stmt||','||SQLNAME_DATA||' '||SQLTYPEF;
   fetch c1 into SQLTYPE_ID,SQLNAME_DATA;
 end while;
 close c1;
 set stmt = 
   'declare global temporary table '||tmp_tbl||'('||substr(stmt,3)
 ||') with replace on commit preserve rows not logged';
 execute immediate stmt;
 set stmt = 'insert into '||tmp_tbl||' '||sel_stmt;
 execute immediate stmt;

 -- construct select statement
 set stmt = 'select distinct rtrim(char('||col_col||')) from '||tmp_tbl||' order by 1';
 prepare s2 from stmt;
 set stmt='';
 open c2;
 fetch c2 into col_val;
 while (SQLCODE!=100) do
   set stmt = 
     stmt||','||agg_fn||'('
   ||'case when '||col_col||' '
   ||case when col_val is null then 'IS NULL' else ('='||apo||replace(col_val,QUOT1,QUOT1||QUOT1)||apo) end
   ||' then '||agg_col||' end) as '||QUOT2||coalesce(replace(col_val,QUOT2,QUOT2||QUOT2),null_ind)||QUOT2;
   fetch c2 into col_val;
 end while;
 close c2;
 -- add to the select statement groups
 set row_cols = nullif(row_cols,'');
 set stmt = 
   'select '||case when row_cols is not null then row_cols||',' else coalesce(row_cols,'') end
 ||substr(stmt,2)||' from '||tmp_tbl||' '
 ||case when row_cols is not null then ('group by '||row_cols||' order by '||row_cols) else '' end;
 -- execute this statement
 prepare s_out from stmt;
 open c_out;
END@

参数说明:

PARM DESC
sel_stmt 任何用于源数据生成的有效 SELECT 语句
row_cols 最后语句的 GROUP BY 中使用的以逗号分隔的列名列表
col_col 要透视的列名
agg_col 要聚合的列名
agg_fn “agg_col”参数中列名的任何有效 Db2 聚合函数
tmp_tbl 中间结果的DGTT名称
null_ind 空指示符
rc 返回码(OUT)
味精 消息文本(OUT)
stmt 最终生成的SELECT(OUT)

简要说明:
tmp_tbl 中传递的 DGTT 是用 sel_stmt 中传递的 SELECT 语句的结果创建和填充的。 row_colscol_colagg_col 中指定的所有列名都必须在此语句的 SELECT 列表中。
此 DGTT 上的最终 SELECT 语句是使用以下规则动态生成的:

  • 对于 Vx 中传递的列名中的每个不同值 col_col,会生成一个额外的列表达式,例如:,<agg_fn> (case when <col_col> = Vx then <agg_col> end) as "Vx",<agg_fn> (case when <col_col> IS NULL then <agg_col> end) as "<null_ind>" 用于 Vx IS NULL),其中 <parameter> 表示与此参数一起传递的字符串值。
  • row_cols 列列表用于 GROUP BY,如果它不是 NULL。

用于您的案例:

DECLARE GLOBAL TEMPORARY TABLE SESSION.MYTAB 
(DATE_F,FILE_NM,ROW_ID,COLUMN_NM,COLUMN_VAL)
AS
(
VALUES
  ('20200131','ABC.TXT',1,'ABC_COL1','123'),('20200131','ABC_COL2','XYZ'),('20201231',2,'456'),'XY1'),('20200630','XYZ.TXT','XYZ_COL1','PQR'),'XYZ_COL2','567'),'XYZ_COL3','MNO')
) WITH DATA WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED;

第一次调用:

call pivot
(
  'select * from session.mytab where file_nm = ''ABC.TXT''','DATE_F,ROW_ID','COLUMN_NM','COLUMN_VAL','max','session.tab1','-',?,?
);
DATE_F ROW_ID ABC_COL1 ABC_COL2
20200131 1 123 XYZ
20201231 2 456 XY1

第二次调用:

call pivot
(
  'select * from session.mytab where file_nm = ''XYZ.TXT''',?
);
DATE_F ROW_ID XYZ_COL1 XYZ_COL2 XYZ_COL3
20200630 1 PQR 567 移动网络运营商

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

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-