【问题标题】:Extract words from a comma separated string in oracle从oracle中的逗号分隔字符串中提取单词
【发布时间】:2015-05-29 06:54:08
【问题描述】:

假设我有字符串

Str = 'Aaa,Bbb,Abb,Ccc'

我想把上面的str分成两部分,如下

Str1 = 'Aaa,Abb'

Str2 = 'Bbb,Ccc'

str 中任何以 A 开头的单词都应该放在 str1 中,其余的都放在 str2 中。

如何使用 Oracle 查询来实现这一点?

【问题讨论】:

  • 永远不要将数据存储为逗号分隔的项目。那只会给你带来很多问题。 SQL 不是为此而设计的,而是有单独的行。
  • @jarlh 评论的补充——您可以使用嵌套表或其他集合类型。

标签: sql string oracle comma


【解决方案1】:

str 中以 A 开头的任何单词都应该放在 str1 中,其余的都放在 str2 中。

要在纯 SQL 中实现它,我将使用以下内容:

  • REGEXP_SUBSTR
  • 列表
  • SUBSTR
  • 内联视图

所以,首先我将使用Split single comma delimited string into rows 此处演示的技术拆分逗号分隔的字符串。

然后,我将使用 LISTAGG 将它们按顺序聚合。

例如,

SQL> WITH
  2  t1 AS (
  3  SELECT 'Aaa,Bbb,Abb,Ccc' str FROM dual
  4        ),
  5  t2 AS (
  6  SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
  7    FROM t1
  8  CONNECT BY LEVEL <= regexp_count(str, ',')+1
  9  ORDER BY str
 10        )
 11  SELECT
 12    (SELECT listagg(str, ',') WITHIN GROUP(
 13    ORDER BY NULL) str1
 14    FROM t2
 15    WHERE SUBSTR(str, 1, 1)='A'
 16    ) str1,
 17    (SELECT listagg(str, ',') WITHIN GROUP(
 18    ORDER BY NULL) str
 19    FROM t2
 20    WHERE SUBSTR(str, 1, 1)<>'A'
 21    ) str2
 22  FROM dual
 23  /

STR1       STR2
---------- ----------
Aaa,Abb    Bbb,Ccc

SQL>

WITH 子句仅用于演示目的,在您的实际场景中,删除 with 子句并直接使用您的表名。虽然使用 WITH 子句看起来很整洁。

【讨论】:

    【解决方案2】:

    使用正则表达式和 ListAg 函数。

    注意:从 Oracle 11g 开始提供 LISTAGG 函数!

    select listagg(s.name, ',') within group (order by name)
      from (select regexp_substr('Aaa,Bbb,Abb,Ccc,Add,Ddd','[^,]+', 1, level) name from dual
           connect by regexp_substr('Aaa,Bbb,Abb,Ccc,Add,Ddd', '[^,]+', 1, level) is not null) s
    group by decode(substr(name,1,1),'A', 1, 0);
    

    【讨论】:

    • OP 想要在两个不同的列中。
    【解决方案3】:

    此查询在两个不同的行中为您提供所需的输出:

    with temp as (select trim (both ',' from 'Aaa,Bbb,Abb,Ccc') as str from dual),
         base_table as
             (    select trim (regexp_substr (t.str,
                                              '[^' || ',' || ']+',
                                              1,
                                              level))
                             str
                    from temp t
              connect by instr (str,
                                ',',
                                1,
                                level - 1) > 0),
         ult_table as
             (select str,
                     case upper (substr (str, 1, 1)) when 'A' then 1 else 2 end
                         as l
                from base_table)
    select listagg (case when l = 1 then str else null end, ',')
               within group (order by str)
               str1,
           listagg (case when l = 2 then str else null end, ',')
               within group (order by str)
               str2
      from ult_table;
    

    输出

             L STR
    ---------- --------------------------------------------------------------------------------
             1 Aaa,Abb                                                                         
             2 Bbb,Ccc       
    

    【讨论】:

    • OP 想要在两个不同的列中。
    • @LalitKumarB- 感谢您注意到这一点。修改了代码。
    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 2013-06-24
    相关资源
    最近更新 更多