Oracle SQL - 如何将多个列合并成新的列?

问题描述 投票:0回答:1

我需要将多个列(有相当多的列和行)合并成新的一列。

例如:缩短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

先谢谢你,米哈乌

sql oracle plsql data-warehouse
1个回答
0
投票

你可以使用 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)
           )

0
投票

试试像这样的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;
/

0
投票

我会按照@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));
© www.soinside.com 2019 - 2024. All rights reserved.