Oracle SQL - Как объединить несколько столбцов в новый - PullRequest
1 голос
/ 28 мая 2020

Мне нужно объединить несколько столбцов (столбцов и строк довольно много) в новый столбец.

Например. сокращенная 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 я хотел бы иметь например: 942,72987,14759,441277503,73553030

Есть ли какое-нибудь решение, как это сделать в SQL / PL / SQL? Как я уже сказал, столбцов много, поэтому я бы не хотел добавлять их вручную, используя Col1 || Col2 || Col3 || Col4 || Col5

Заранее спасибо, Michał

Ответы [ 3 ]

0 голосов
/ 28 мая 2020

Я бы пошел по маршруту @ AP C и использовал бы запрос 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

Теперь я бы скопировал и вставил это в соответствующий запрос, fi

UPDATE t 
   SET col6 = COL1||','||COL2||','||COL3||','||COL4||','||COL5;

Чтобы объединить столбцы, их нужно преобразовать в VARCHAR2. Oracle пытается автоматическое преобразование c типа данных. Вы должны проверить, работает ли это и достаточно ли это для вас. В числах могут быть начальные пробелы, запятая или десятичная точка, для дат может потребоваться строка формата et c.

Вы можете подумать о том, чтобы сделать это в следующих строках:

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));
0 голосов
/ 28 мая 2020

Попробуйте блок 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;
/
0 голосов
/ 28 мая 2020

Вы можете использовать trim() с некоторыми условными логами c:

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)
           )
...