【问题标题】:splitting two columns containing comma separated values in oracle [duplicate]在oracle中拆分包含逗号分隔值的两列[重复]
【发布时间】:2020-08-28 06:52:27
【问题描述】:

我在一个表中有两列,用逗号分隔值,如何将其拆分为行?

【问题讨论】:

  • 有很多选择,for example
  • @micklesh 部分是的,但问题是我在一个表中有两列用逗号分隔值,我该如何拆分它们?
  • 一个最简单(但不正确)的选项 - 将 2 列合并为一个值并考虑该连接字段。或者单独处理字段,然后合并结果
  • 为测试用例提供ddl、表数据和预期输出。
  • this 有帮助吗? "listunagg 函数"

标签: sql oracle plsql


【解决方案1】:

这会有帮助吗?

SQL> with test (col1, col2) as
  2    (select 'Little,Foot,is,stupid', 'poor,bastard'         from dual union all
  3     select 'Green,mile,is,a'      , 'good,film,is,it,not?' from dual
  4    )
  5  select regexp_substr(col1 ||','|| col2, '[^,]+', 1, column_value) str
  6  from test cross join
  7       table(cast(multiset(select level from dual
  8                           connect by level <= regexp_count(col1 ||','|| col2, ',') + 1
  9                          ) as sys.odcinumberlist));

STR
--------------------------------------------------------------------------------
Little
Foot
is
stupid
poor
bastard
Green
mile
is
a
good
film
is
it
not?

15 rows selected.

SQL>

【讨论】:

    【解决方案2】:

    使用递归子查询分解子句和简单的字符串函数:

    WITH splits ( id, c1, c2, idx, start_c1, end_c1, start_c2, end_c2 ) AS (
      SELECT id,
             c1,
             c2,
             1,
             1,
             INSTR( c1, ',', 1 ),
             1,
             INSTR( c2, ',', 1 )
      FROM   test_data
    UNION ALL
      SELECT id,
             c1,
             c2,
             idx + 1,
             CASE end_c1 WHEN 0 THEN NULL ELSE end_c1 + 1 END,
             CASE end_c1 WHEN 0 THEN NULL ELSE INSTR( c1, ',', end_c1 + 1 ) END,
             CASE end_c2 WHEN 0 THEN NULL ELSE end_c2 + 1 END,
             CASE end_c2 WHEN 0 THEN NULL ELSE INSTR( c2, ',', end_c2 + 1 ) END
      FROM   splits
      WHERE  end_c1 > 0
      OR     end_c2 > 0
    )
    SELECT id,
           idx,
           CASE end_c1
           WHEN 0
           THEN SUBSTR( c1, start_c1 )
           ELSE SUBSTR( c1, start_c1, end_c1 - start_c1 )
           END AS c1,
           CASE end_c2
           WHEN 0
           THEN SUBSTR( c2, start_c2 )
           ELSE SUBSTR( c2, start_c2, end_c2 - start_c2 )
           END AS c2
    FROM   splits s
    ORDER BY id, idx;
    

    所以对于测试数据:

    CREATE TABLE test_data ( id, c1, c2 ) AS
    SELECT 1, 'a,b,c,d', 'e,f,g' FROM DUAL UNION ALL
    SELECT 2, 'h', 'i' FROM DUAL UNION ALL
    SELECT 3, NULL, 'j,k,l,m,n' FROM DUAL;
    

    这个输出:

    身份证 | IDX | C1 | C2 -: | --: | :--- | :--- 1 | 1 |一个 | e 1 | 2 |乙 | F 1 | 3 | c | G 1 | 4 | d | 2 | 1 | h |一世 3 | 1 | | j 3 | 2 | | ķ 3 | 3 | | l 3 | 4 | |米 3 | 5 | | n

    db小提琴here

    【讨论】:

    • 任何更简单的方法
    • @VinodNM 你要问的不是“简单”,所以你不会找到一个简单的单行答案。这个答案非常“简单”......它只是遍历字符串,在递归子查询因式分解子句中找到逗号,然后在底部找到这些逗号之间的子字符串。有很多“其他”方式,包括正则表达式、使用表集合表达式或自定义函数的自连接,但这可能是更“有效”的方式之一,因为它不涉及到自定义函数的 PL/SQL 上下文切换也不会加入。
    猜你喜欢
    • 1970-01-01
    • 2015-04-01
    • 2017-07-04
    • 2011-07-26
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2010-10-23
    相关资源
    最近更新 更多