sql - 如何使用 DB2 sql 代码动态地将列转置为表的行,其中列可能会随着时间的推移而增加且无需更改代码?
问题描述
我有一个表格,其中列最终会随着时间的推移而增加。我想编写一个查询来转置表,即使后来的列增加,也不需要添加额外的代码行来实现它。我需要转置值为'Y'的那些列
Eg: Source data on day 1
| Emp_ID | DOC 1 | DOC 2 |
| ------ |-------|-------|
| 001 | Y |Y |
| 002 | N |Y |
Day 1 output
| Emp_ID | Transposed |
| ------ |-------|
| 001 | DOC 1 |
| 001 | DOC 2 |
| 002 | DOC 2 |
现在最终列可能会增加,并且希望在不更改代码的情况下使用相同的查询块来处理它,可以吗?
Source data on day 2
| Emp_ID | DOC 1 | DOC 2 | DOC 3|
| ------ |-------|-------|------|
| 001 | Y |Y |N |
| 002 | N |Y |Y |
| 003 | N |N |N |
Day 2 output
| Emp_ID | Transposed |
| ------ |-------|
| 001 | DOC 1 |
| 001 | DOC 2 |
| 002 | DOC 2 |
| 002 | DOC 3 |
**Note have considered only docs having Y as a value. Thanks in advance**
解决方案
您需要为给定的基表动态构造以下语句
MYSCHEMA.MYTAB (EMP_ID INT, DOC1 CHAR, ..., DOCn CHAR)
:
SELECT T.EMP_ID, V.COLNAME
FROM
MYSCHEMA.MYTAB T
, (
SELECT COLNAME
FROM SYSCAT.COLUMNS
WHERE TABSCHEMA = 'MYSCHEMA' AND TABNAME = 'MYTAB' AND COLNAME <> 'EMP_ID' AND TYPENAME LIKE '%CHAR%'
) V
WHERE
V.COLNAME = 'DOC1' AND T.DOC1 = 'Y'
...
OR V.COLNAME = 'DOCn' AND T.DOCn = 'Y'
该语句只有动态WHERE
部分。子选择SYSCAT.COLUMNS
返回所有要转置的表列(除 之外的所有表列EMP_ID
)。
表函数中的以下SELECT INTO
语句生成任何数量的此类列所需的最终语句。
CREATE OR REPLACE FUNCTION MYFUNC ()
RETURNS TABLE (EMP_ID INT, TRANSPOSED VARCHAR (128))
BEGIN
DECLARE V_SQL VARCHAR (4000);
DECLARE V_EMP_ID INT;
DECLARE V_TRANSPOSED VARCHAR (128);
DECLARE SQLSTATE CHAR(5);
DECLARE C1 CURSOR FOR S1;
SELECT
'SELECT T.EMP_ID, V.COLNAME '
|| 'FROM '
|| ' MYSCHEMA.MYTAB T '
|| ', ( '
|| 'SELECT COLNAME '
|| 'FROM SYSCAT.COLUMNS '
|| 'WHERE TABSCHEMA = ''MYSCHEMA'' AND TABNAME = ''MYTAB'' AND COLNAME <> ''EMP_ID'' AND TYPENAME LIKE ''%CHAR%'''
|| ' ) V '
|| 'WHERE '
|| LISTAGG ('V.COLNAME = ''' || COLNAME || ''' AND T.' || COLNAME || ' = ''Y''', ' OR ')
INTO V_SQL
FROM SYSCAT.COLUMNS
WHERE TABSCHEMA = 'MYSCHEMA' AND TABNAME = 'MYTAB' AND COLNAME <> 'EMP_ID' AND TYPENAME LIKE '%CHAR%';
PREPARE S1 FROM V_SQL;
OPEN C1;
L1: LOOP
FETCH C1 INTO V_EMP_ID, V_TRANSPOSED;
IF SQLSTATE = '02000' THEN LEAVE L1; END IF;
PIPE (V_EMP_ID, V_TRANSPOSED);
END LOOP L1;
CLOSE C1;
RETURN;
END@
推荐阅读
- arrays - Fortran 运行时错误:可分配数组的文件结尾
- git - GIT:在意外提交并推送删除文件后,您能否恢复文件的最新工作版本?
- mysql - 如果行存在,则 SQL 运行命令
- spring - Spring Batch - 在使用 FlatFileItemWriter API 写入数据时创建新的唯一 CSV 名称
- c++ - lambda 中的这个 size_t 有什么作用?C++ 代码
- python - 在 Python 中避免嵌套 if else 语句阶梯
- asp.net - 开始调试 VS2017 ASP.NET 后没有收到此消息
- javascript - 使用表单填充数组
- c - 对于遍历数组,我们应该使用 size_t 还是 ptrdiff_t?
- unity3d - VUFORIA 地平面检测和刚体