需要 PL/SQL 存储过程将列转换为行
Posted
技术标签:
【中文标题】需要 PL/SQL 存储过程将列转换为行【英文标题】:Need PL/SQL stored procedure to convert column into rows 【发布时间】:2020-12-14 17:29:38 【问题描述】:我有桌子-
filename description value
-------- ------------------------------------------ --------------------
rec_123 PropertyWriteCount_rows_0_month February 2018
rec_123 rows_PropertyWriteCount_rows_0_description property write count
rec_123 PropertyWriteCount_rows_0_value_value 1234
rec_123 PropertyWriteCount_rows_0_value_baseType LONG
我想把它转换成-
filename month value description value_basetype
-------- ------------- ----- ------------------------- --------------
rec_2134 February 2018 1234 PropertyWriteCount_rows_0 long
到目前为止,我可以编写 PL/SQL,需要帮助进行下一步 -
CREATE PROCEDURE rows_column IS
CURSOR get_rows IS
SELECT * FROM table1 where description LIKE 'PropertyWriteCount_rows%';
BEGIN
DBMS_OUTPUT.PUT_LINE('table info -');
END;
/
【问题讨论】:
【参考方案1】:您可以使用条件聚合来做到这一点:
select
filename,
max(case when description = 'PropertyWriteCount_rows_0_month' then value end) as month,
max(case when description = 'rows_PropertyWriteCount_rows_0_description' then value end) as description,
max(case when description = 'PropertyWriteCount_rows_0_value_value' then value end) as value,
max(case when description = 'PropertyWriteCount_rows_0_value_baseType' then value end) as value_basetype
from table1
where description like '%PropertyWriteCount_rows%'
group by filename
【讨论】:
谢谢,我发现了 2 个问题 1) 这生成了文件名列 (rec_2134) 的单个记录,但我有多个记录如何处理它 2) 我的描述不会总是“PropertyWriteCount_rows_0”,可以我们添加类似的情况? (1) 这未显示在您的示例数据中,因此我无法对此发表评论 (2) 当然,您可以将等式更改为like
条件。例如:max(case when description like 'PropertyWriteCount_rows_%_month' then value end) as month
.
我仍然想了解如果我必须获取多个文件名记录,那么我们该如何处理?
@AkashSarpate - 请编辑您的问题以包含更多示例数据。如果输出中有多行具有相同的filename
,您如何知道要将哪些行聚合在一起?当您编辑您的问题并包含该示例数据时,请务必说明您要实施的逻辑,以选择要在输出中组合哪些行。【参考方案2】:
您可以在呈现description
列后使用PIVOT
子句,以便从该列中提取最后一个下划线之后的最后一个单词。
以下查询可能用作静态方法
SELECT *
FROM
(
SELECT REGEXP_SUBSTR(description,'[^_]+$') AS title,
filename, value
FROM table1 )
PIVOT
(
MAX(value) FOR title IN ('month' AS month, 'value' AS value,
'description' AS description, 'baseType' AS baseType)
)
Demo
但应该首选动态方法,通过创建存储函数,如以下 PL/SQL 代码中所示
CREATE OR REPLACE FUNCTION Get_File_Values RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_col VARCHAR2(32767);
BEGIN
SELECT LISTAGG( ''''||titles||''' AS '||titles , ',' )
WITHIN GROUP ( ORDER BY titles DESC )
INTO v_col
FROM ( SELECT DISTINCT REGEXP_SUBSTR(description,'[^_]+$') AS titles
FROM table1 );
v_sql :=
'SELECT *
FROM (
SELECT REGEXP_SUBSTR(description,''[^_]+$'') AS title,
filename, value
FROM table1
)
PIVOT
(
MAX(value) FOR title IN ( '|| v_col ||' )
)';
OPEN v_recordset FOR v_sql;
DBMS_OUTPUT.PUT_LINE(v_sql);
RETURN v_recordset;
END;
/
然后运行以下代码:
VAR rc REFCURSOR
EXEC :rc := Get_File_Values;
PRINT rc
来自 SQL Developer 的命令行
或
BEGIN
:result := Get_File_Values;
END;
来自PL/SQL Developer的测试窗口(标记为)
为了查看预期结果集的变化,即使 description
列的新值被插入或一些以前的值被删除。
【讨论】:
以上是关于需要 PL/SQL 存储过程将列转换为行的主要内容,如果未能解决你的问题,请参考以下文章