私はこのようなテーブルを持っています:
| 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から複数)を含め、2つの結合された副選択の行を一致させることにより、特定の結果のニーズに合わせて変更できます。
パーティーには少し遅れましたが、最近のプロジェクトで、より単純なソリューションで同様のことを達成する必要があり、再帰的なSQLではなくXMLTABLEを使用してこのアプローチを共有する必要があると考えました。
データのセットアップは、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
値タグを取り除くことで、XMLTABLE()を介して最後のソリューションを短縮することもできます。
SELECT sd.ID, sd.OtherId, si.item as NewId
from session.sample_data sd
,XMLTABLE('$doc/items/item'
PASSING XMLPARSE(DOCUMENT CAST( '<items><item>'
|| replace(sd.Data , ',' , '</item><item>')
|| '</item></items>' as CLOB
)
) as "doc"
COLUMNS
ITEM VARCHAR(255) PATH '.'
) si ;