我需要将多个列(有相当多的列和行)合并成新的一列。
例如:缩短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用逗号分隔符(",")合并,并把创建的字符串放到Col6中。
因此,在Col6中,我想有eg。942,72987,14759,441277503,73553030
有什么解决办法吗? 我说过有很多列,所以我想避免手动添加它们,使用的是 Col1 || Col2 || Col3 || Col4 || Col5
先谢谢你,米哈乌
你可以使用 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)
)
试试像这样的PLSQL块
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;
/
我会按照@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));