Oracle SQL - 如何将多列合并为新列
Posted
技术标签:
【中文标题】Oracle SQL - 如何将多列合并为新列【英文标题】:Oracle SQL - How to merge multiple columns into new one 【发布时间】:2020-05-28 13:34:05 【问题描述】:我需要将多列(有很多列和行)合并到新的一列中。
例如。缩短的 test_table
Col1 Col2 Col3 Col4 Col5 Col6
942 72987 14759 441277503 73553030 null
943 72987 14759 441278315 73553166 null
944 72987 14759 441362593 73570082 null
945 72987 14759 441380217 73572619 null
946 72987 14759 441394189 73574533 null
947 72987 14759 441394189 73574533 null
我想将 Col1-Col5 与逗号分隔符 (",") 合并,并将创建的 String 放入 Col6
所以在 Col6 中,我想拥有例如:
942,72987,14759,441277503,73553030
有什么解决方案可以在 SQL/PL/SQL 中执行吗?
正如我所说的有很多列,所以我想避免使用Col1 || Col2 || Col3 || Col4 || Col5
手动添加它们
提前致谢, 米哈乌
【问题讨论】:
不。手动是您唯一的选择。虽然如果您想对很多表执行此操作,您可以从数据字典中生成代码。 列为 NULL 时会发生什么?您的列的数据类型是什么? @wolφi - 如果列为 Null,那么它应该只是空白值。并且数据类型不同,主要是 VARCHAR2,但其中一些是 NUMBERs 编辑了我的答案以处理数据类型和转换。请看meta.stackexchange.com/questions/5234/… 【参考方案1】:您可以将trim()
与一些条件逻辑一起使用:
select trim(leading ',' from
(case when col1 is not null then ',' || col1 else '' end) ||
(case when col2 is not null then ',' || col2 else '' end) ||
(case when col3 is not null then ',' || col3 else '' end) ||
(case when col4 is not null then ',' || col4 else '' end) ||
(case when col5 is not null then ',' || col5 else '' end)
)
【讨论】:
【参考方案2】:尝试这样的 PL/SQL 块:
SET SERVEROUT ON
DECLARE
LV_COLUMNS VARCHAR2(20000);
BEGIN
SELECT LISTAGG('CASE WHEN ' || COLUMN_NAME || ' IS NOT NULL THEN ' || COLUMN_NAME || ' || '',''|| '
|| 'ELSE NULL END'
, '||') WITHIN GROUP(ORDER BY COLUMN_ID)
INTO LV_COLUMNS
FROM USER_TAB_COLS
WHERE TABLE_NAME = 'YOUR_TABLE_NAME'
AND COLUMN_NAME <> 'COL6'
AND HIDDEN_COLUMN = 'NO';
DBMS_OUTPUT.PUT_LINE('UPDATE YOUR_TABLE_NAME SET COL6 = TRIM('','' FROM (' || LV_COLUMNS || '))');
EXECUTE IMMEDIATE 'UPDATE YOUR_TABLE_NAME SET COL6 = TRIM('','' FROM (' || LV_COLUMNS || '))';
COMMIT;
END;
/
【讨论】:
【参考方案3】:我会遵循@APC 的路线并使用USER_TAB_COLUMNS
的查询来生成必要的SQL:
CREATE TABLE t (col1 VARCHAR2(5), col2 NUMBER, col3 VARCHAR2(30),
col4 VARCHAR2(7), col5 DATE, col6 VARCHAR2(200));
SELECT column_name
FROM user_tab_columns
WHERE table_name = 'T'
AND column_name <> 'COL6';
COL1
COL2
COL3
COL4
COL5
您现在可以将它们与LISTAGG 连接起来:
SELECT LISTAGG(column_name, '||'',''||')
WITHIN GROUP (ORDER BY column_id) AS sql
FROM user_tab_columns
WHERE table_name = 'T'
AND column_name <> 'COL6';
COL1||','||COL2||','||COL3||','||COL4||','||COL5
现在我将其复制并粘贴到相应的查询中,f.i.
UPDATE t
SET col6 = COL1||','||COL2||','||COL3||','||COL4||','||COL5;
要连接列,需要将它们转换为 VARCHAR2。 Oracle 尝试进行自动数据类型转换。您必须检查这是否有效并且对您来说足够好。数字可能有前导空格、逗号或小数点,日期可能需要格式字符串等。
你可以考虑按照这些思路来做:
SELECT column_name,
CASE WHEN data_type IN ('NUMBER','FLOAT')
THEN 'TO_CHAR('||column_name||')'
WHEN data_type IN ('DATE')
THEN 'TO_CHAR('||column_name||',''YYYY-MM-DD'')'
ELSE column_name
END AS cstr
FROM user_tab_columns
WHERE table_name = 'T'
AND column_name <> 'COL6';
COL1 COL1
COL2 TO_CHAR(COL2)
COL3 COL3
COL4 COL4
COL5 TO_CHAR(COL5,'YYYY-MM-DD')
根据您的情况,您可以使用虚拟列而不是复制真实数据:
ALTER TABLE t DROP COLUMN col6;
ALTER TABLE t ADD (col6 NUMBER GENERATED ALWAYS
AS (COL1||','||COL2||','||COL3||','||COL4||','||COL5));
【讨论】:
以上是关于Oracle SQL - 如何将多列合并为新列的主要内容,如果未能解决你的问题,请参考以下文章