[英]Two Columns with Delimiter into Multiple Rows
我首先要说这个答案非常相似。 如果这是我问题的真正解决方案,我会提前道歉。
通过将两个 sql 列与分隔数据合并到一个带有分隔数据的列中
我在 Oracle 数据库中有一个表,其中两列具有用管道 (|) 分隔的分隔值。 这些列中的值相互对应。 这意味着 col1 中 pipe 之前的第一个值与 col2 中 pipe 之前的第一个值相关。 这是示例数据:
钥匙 | col1 | col2 |
---|---|---|
1 | 12345678|87654321 | ABABABAB|CDCDCDCD |
2 | 12345678|87654321 | ABABABAB|EFEFEFEF |
3 | 12345678|11223344 | ABABABAB|ZXZXZXZX |
4 | 12345678|11223344 | ABABABAB|ZXZXZXZX |
我需要将这些列分成几行,并在同一行中有相应的数据,如下所示:
钥匙 | col1 | col2 |
---|---|---|
1 | 12345678 | ABABABAB |
1 | 87654321 | CDCCDCD |
2 | 12345678 | ABABABAB |
2 | 87654321 | EFEFEFEF |
3 | 12345678 | ABABABAB |
3 | 11223344 | ZXZXZXZX |
4 | 12345678 | ABABABAB |
4 | 11223344 | ZXZXZXZX |
任何帮助表示赞赏。
如果总是有两个值并且它们具有相同的长度 - 就像您示例中的数据一样 - 那么union all
是一种非常简单的方法:
select key, substr(col1, 1, 8), substr(col2, 1, 8)
from t
union all
select key, substr(col1, 10), substr(col2, 10)
from t;
如果它们的长度不同,但总是有两个值,那么regexp_substr()
非常方便:
select key, regexp_substr(col1, '^[^|]+'), regexp_substr(col1, '[^|]+$')
from t
union all
select key, regexp_substr(col1, '^[^|]+'), regexp_substr(col1, '[^|]+$')
from t;
如果您有更多值,它确实会变得更加复杂,但您的样本数据表明您只有两个。
更通用的方法使用递归 CTE:
with cte(key, val1, val2, rest1, rest2, lev) as (
select key, null, null, col1 || '|', col2 || '|', 0
from t
union all
select key, regexp_substr(rest1, '^[^|]+'), regexp_substr(rest2, '^[^|]+'),
substr(rest1, instr(rest1, '|') + 1), substr(rest2, instr(rest2, '|') + 1),
lev + 1
from cte
where rest1 is not null and rest2 is not null
)
select key, val1, val2
from cte
where lev <> 0
这是一个 db<>fiddle。
您可以使用带有REGEXP_SUBSTR()
函数的分层查询来拆分列,例如
SELECT key,
REGEXP_SUBSTR(col1,'[^|]+',1,level) AS col1,
REGEXP_SUBSTR(col2,'[^|]+',1,level) AS col2
FROM t
CONNECT BY level <= GREATEST( REGEXP_COUNT(col1,'[|]')+1, REGEXP_COUNT(col2,'[|]')+1 )
AND PRIOR SYS_GUID() IS NOT NULL
AND PRIOR key = key
ORDER BY key, level
通过为每个键生成最大行数,具体取决于两列中的每一列可能包含当前数据集中每一行的相同或不同数量的 pipe 字符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.