我有下表(引用的数量是可变的):
Id | FK_ID| Reference |
-----------------------
1 2100 GI2, GI32
2 2344 GI56
我需要以下结果:
Id | FK_ID| Reference |
-----------------------
1 2100 GI2
2 2100 GI32
3 2344 GI56
是否有使用DB2转换数据的简短方法?
答案 0 :(得分:6)
你真的不应该存储这样的数据。幸运的是,有一种方法可以通过递归SQL来消除损坏,这些都是这样的:
WITH unpivot (lvl, id, fk_ref, reference, tail) AS (
SELECT 1, id, fk_ref,
CASE WHEN LOCATE(',',reference) > 0
THEN TRIM(LEFT(reference, LOCATE(',',reference)-1))
ELSE TRIM(reference)
END,
CASE WHEN LOCATE(',',reference) > 0
THEN SUBSTR(reference, LOCATE(',',reference)+1)
ELSE ''
END
FROM yourtable
UNION ALL
SELECT lvl + 1, id, fk_ref,
CASE WHEN LOCATE(',', tail) > 0
THEN TRIM(LEFT(tail, LOCATE(',', tail)-1))
ELSE TRIM(tail)
END,
CASE WHEN LOCATE(',', tail) > 0
THEN SUBSTR(tail, LOCATE(',', tail)+1)
ELSE ''
END
FROM unpivot
WHERE lvl < 100 AND tail != '')
SELECT id, fk_ref, reference FROM unpivot
PS。未经测试。
答案 1 :(得分:0)
我做了类似于posstr(修剪(ROW,&#39; [DELIMITER]&#39;)),LENGTH .. 像:
Table
NAME
---------------------
Martin, Example
SELECT
CASE WHEN POSSTR(NAME, ',') > 0
THEN SUBSTR(TRIM(NAME), POSSTR(TRIM(NAME), ',') + 1), LENGTH(TRIM(NAME)) - POSSTR(TRIM(NAME),',')))
ELSE 'ERROR'
END
FROM ...
UNION ALL
..
Result: Example
但未经过测试,..可能会有空的结果集,之后必须删除它们。
答案 2 :(得分:0)
我在Split comma separated entries to rows
下发布了此类转化的通用解决方案要查看此示例数据的结果,请将会话数据替换为:
INSERT INTO session.sample_data SELECT 1, 2100, 'GI2,GI32' FROM sysibm.sysdummy1;
INSERT INTO session.sample_data SELECT 2, 2344, 'GI56' FROM sysibm.sysdummy1;
结果:
ID OTHERID DATA
1 2100 GI2
1 2100 GI32
2 2344 GI56
答案 3 :(得分:0)
第一关,我不知道为什么这么多人说您在进行ETL时不应该以这种方式存储数据。他们显然不了解ETL开发人员实际上在做什么。这是他们很少控制所接收数据的格式,但必须使其在传递到目的地时表现得更好。好吧,放空:这是我的建议。
我将带分隔符的列表转换为动态SQL语句的Values子句,以从中选择或使用它动态创建要使用的表或视图...获得数据透视后的可能性非常简单。这是一个小代码段,您可以轻松地将其嵌入到存储过程中。...这假定是DB2的最新版本(希望持续4/5年)。...
declare sDelimitString as Varchar(500);
declare sValues as Varchar(1000);
set sDelimitString = 'Data 1,Data 2,Data 3';
set sValues = ''' Values((' || Replace((sDelimitString,',','''),(''') || '))'' as PIVOT_DATA(SOME_COLUMN_NAME) ';
declare cCur Cursor with return for aStmt;
set sSQL = Select PIVOT_DATA.SOME_COLUMN_NAME FROM ' || sValues;
prepare aStmt from sSQL;
open cCur;
想法是使用值语句,例如“从(Values(1),(2),(3))中选择C1作为T1(C1)”。您甚至可以将这部分变成更大的SQL语句的一部分,该语句可以完全选择并动态返回结果,将数据插入到tmp表中,或者动态创建视图等...
现在,DB2只是与动态游标,Oracle,SQL Server或几乎任何其他数据库相比很奇怪。以我的经验,声明cCur行必须是存储的proc中的最后一个“声明”语句,否则procs不会编译,并且在google上没有显示它的原因。...这很痛苦,不应该,但是我我们在其他地区的db2中多次发现了同样的痛苦。同样,一旦有了枢轴,就可以使用它进行任何操作。 sSQL不必一定是select语句,它可以是动态构建临时表或视图以从中拉出的命令。祝您好运...我知道太晚了..但是我不是这里的解决方案或评论的忠实粉丝。