Db2

將逗號分隔的條目拆分為行

  • April 15, 2020

我有一張這樣的桌子:

|   ID   |  OtherID  | Data
+--------+-----------+---------------------------
|  5059  |   73831   | 5103,5107
|  5059  |   73941   | 5103,5104,5107
|  5059  |   73974   | 5103,5106,5107,5108

結果應該返回單獨的行,如下所示:

|   ID   |  OtherID  | Data
+--------+-----------+--------------------------
|  5059  |   73831   | 5103
|  5059  |   73831   | 5107
|  5059  |   73941   | 5103
|  5059  |   73941   | 5104
|  5059  |   73941   | 5107
|  5059  |   73974   | 5103
|  5059  |   73974   | 5106
|  5059  |   73974   | 5107
|  5059  |   73974   | 5108

基本上,我需要將逗號處的數據拆分為單獨的行。

結果將儲存在臨時表中(如:)ID, OtherID, NewID

我的 DB2 版本是 9.7

我根據我正在做的一些工作以及對Serge Rielau 和 Rick Swagerman 在 IBM developerWorks 上發布的解決方案的一些修改,為您的數據集提出了一個解決方案。

數據設置查詢:

DECLARE GLOBAL TEMPORARY TABLE sample_data (id INTEGER, otherid integer, data VARCHAR(255)) WITH REPLACE ON COMMIT preserve rows NOT logged;
INSERT INTO session.sample_data SELECT 5059, 73831, '5103,5107' FROM sysibm.sysdummy1;
INSERT INTO session.sample_data SELECT 5059, 73941, '5103,5104,5107' FROM sysibm.sysdummy1;
INSERT INTO session.sample_data SELECT 5059, 73974, '5103,5106,5107,5108' FROM sysibm.sysdummy1;

解決方案選擇查詢:

WITH
split_data AS
(
   SELECT
       id as group_by_1,
       otherid as group_by_2,
       data AS split_string,
       ','  AS split
   FROM
       session.sample_data
)
,
rec
(
   group_by_1,
   group_by_2,
   split_string,
   split,
   row_num,
   column_value,
   pos
) AS
(
   SELECT
       group_by_1,
       group_by_2,
       split_string,
       split,
       1,
       VARCHAR(SUBSTR(split_string, 1, DECODE(INSTR(split_string, split, 1), 0, LENGTH(split_string), INSTR(split_string, split, 1) - 1)), 255),
       INSTR(split_string, split, 1) + LENGTH(split)
   FROM
       split_data
   UNION ALL
   SELECT
       group_by_1,
       group_by_2,
       split_string,
       split,
       row_num + 1,
       VARCHAR(SUBSTR(split_string, pos, DECODE(INSTR(split_string, split, pos), 0, LENGTH(split_string) - pos + 1, INSTR(split_string, split, pos) - pos)), 255),
       INSTR(split_string, split, pos) + LENGTH(split)
   FROM
       rec
   WHERE
       row_num < 30000
   AND pos > LENGTH(split)
)
SELECT
   group_by_1 as id,
   group_by_2 as otherid,
   column_value AS data
FROM
   rec
ORDER BY
   group_by_1,
   group_by_2,
   row_num;

結果:

ID  OTHERID DATA
5059    73831   5103
5059    73831   5107
5059    73941   5103
5059    73941   5104
5059    73941   5107
5059    73974   5103
5059    73974   5106
5059    73974   5107
5059    73974   5108

註釋:

通過在 REC 表定義中包含盡可能多的 GROUP_BY_X 行(O 到多個)並在兩個聯合子選擇中匹配行,可以修改解決方案選擇查詢以滿足您的特定結果需求。

聚會有點晚了,但我最近有一個項目,我需要用更簡單的解決方案完成類似的事情,並認為我應該使用 XMLTABLE 而不是遞歸 SQL 來分享這種方法。

數據設置

數據設置與 Jeff Rudnick 的回答相同。

DECLARE GLOBAL TEMPORARY TABLE session.sample_data (
   ID        INTEGER,
   OtherId   INTEGER,
   Data      VARCHAR(255)
   )
   WITH REPLACE ON COMMIT PRESERVE ROWS NOT LOGGED;
INSERT INTO session.sample_data values
   (5059, 73831, '5103,5107'),
   (5059, 73941, '5103,5104,5107'),
   (5059, 73974, '5103,5106,5107,5108');

解決方案

SELECT sd.ID, sd.OtherId, si.item as NewId
 from session.sample_data sd
     ,XMLTABLE('$doc/items/item'
         PASSING XMLPARSE(DOCUMENT CAST('<items><item><value>'||replace(sd.Data,',','</value></item><item><value>')||'</value></item></items>' as CLOB)) as "doc"
         COLUMNS
         ITEM VARCHAR(255) PATH 'value'
     ) si
;

結果

ID     OTHERID   NEWID
5059   73831     5103
5059   73831     5107
5059   73941     5103
5059   73941     5104
5059   73941     5107
5059   73974     5103
5059   73974     5106
5059   73974     5107
5059   73974     5108

引用自:https://dba.stackexchange.com/questions/73221