计算列逗号分隔值 oracle

Posted

技术标签:

【中文标题】计算列逗号分隔值 oracle【英文标题】:Count column comma delimited values oracle 【发布时间】:2019-10-14 18:23:34 【问题描述】:

是否可以对 oracle 数据库表中的逗号分隔值进行计数和分组?这是一个表格数据示例:

id | user | title | 
1  | foo  | a,b,c |
2  | bar  | a,d   |
3  | tee  | b     |

预期的结果是:

title | count
a     | 2
b     | 2
c     | 1
d     | 1

我想像这样使用 concat:

SELECT a.title FROM Account a WHERE concat(',', a.title, ',') LIKE 'a' OR concat(',', a.title, ',') LIKE 'b' ... GROUP BY a.title?

但我在 concat 上收到 invalid number of arguments。标题值是预定义的,因此我不介意是否必须在查询中列出所有这些值。非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

这使用简单的字符串函数和递归子查询分解,可能比使用正则表达式和相关连接更快:

Oracle 设置

CREATE TABLE account ( id, "user", title ) AS
  SELECT 1, 'foo', 'a,b,c' FROM DUAL UNION ALL
  SELECT 2, 'bar', 'a,d'   FROM DUAL UNION ALL
  SELECT 3, 'tee', 'b'     FROM DUAL;

查询

WITH positions ( title, start_pos, end_pos ) AS (
  SELECT title,
         1,
         INSTR( title, ',', 1 )
  FROM   account
UNION ALL
  SELECT title,
         end_pos + 1,
         INSTR( title, ',', end_pos + 1 )
  FROM   positions
  WHERE  end_pos > 0
),
items ( item ) AS (
  SELECT CASE end_pos
         WHEN 0
         THEN SUBSTR( title, start_pos )
         ELSE SUBSTR( title, start_pos, end_pos - start_pos )
         END
  FROM   positions
)
SELECT item,
       COUNT(*)
FROM   items
GROUP BY item
ORDER BY item;

输出

项目 |数数(*) :--- | --------: 一个 | 2 乙 | 2 c | 1 d | 1

db小提琴here

【讨论】:

【参考方案2】:

将标题拆分为行并计算它们。

SQL> with test (id, title) as
  2    (select 1, 'a,b,c' from dual union all
  3     select 2, 'a,d'   from dual union all
  4     select 3, 'b'     from dual
  5    ),
  6  temp as
  7    (select regexp_substr(title, '[^,]', 1, column_value) val
  8     from test cross join table(cast(multiset(select level from dual
  9                                              connect by level <= regexp_count(title, ',') + 1
 10                                             ) as sys.odcinumberlist))
 11    )
 12  select val as title,
 13         count(*)
 14  From temp
 15  group by val
 16  order by val;

TITLE                  COUNT(*)
-------------------- ----------
a                             2
b                             2
c                             1
d                             1

SQL>

如果标题不是那么简单,则在第 7 行修改REGEXP_SUBSTR(添加+ 符号),例如

SQL> with test (id, title) as
  2    (select 1, 'Robin Hood,Avatar,Star Wars Episode III' from dual union all
  3     select 2, 'Mickey Mouse,Avatar'   from dual union all
  4     select 3, 'The Godfather'     from dual
  5    ),
  6  temp as
  7    (select regexp_substr(title, '[^,]+', 1, column_value) val
  8     from test cross join table(cast(multiset(select level from dual
  9                                              connect by level <= regexp_count(title, ',') + 1
 10                                             ) as sys.odcinumberlist))
 11    )
 12  select val as title,
 13         count(*)
 14  From temp
 15  group by val
 16  order by val;

TITLE                            COUNT(*)
------------------------------ ----------
Avatar                                  2
Mickey Mouse                            1
Robin Hood                              1
Star Wars Episode III                   1
The Godfather                           1

SQL>

【讨论】:

谢谢你,测试。一个问题,这比select(*) 和自己处理计数更快吗? 天哪,介意再帮我一把吗?可以说标题是字符串,而不是字符。您能否在没有测试数据的情况下更新查询。无法让它与我的桌子一起使用。 当然。更改 REGEXP_SUBSTR;在此处添加一个很小的 ​​+ 标志:'[^,]+'。我添加了另一个例子;请看一下。 太棒了!现在只有一个问题。查询的第一部分有效。我收到指向select val as title 的“VAL”:无效标识符。真的很抱歉,我对 SQL 不好:/ 当前查询:collabedit.com/5xydb 您需要使用 CTE(公用表表达式;有些人称之为 WITH factoring 子句)。作为第一行添加例如with temp as,并在最后一行选择 temp 而不是 swuserroles。基本上,模仿我所做的。

以上是关于计算列逗号分隔值 oracle的主要内容,如果未能解决你的问题,请参考以下文章

Oracle Apex - 逗号分隔的 LOV

雪花 - 计算逗号分隔列表中的不同值

使用 oracle sql 以逗号分隔的字符串

Oracle同一字段用逗号分隔(列转行)

将逗号分隔值拆分为 Oracle 中的列

在 Oracle SQL 中求和逗号分隔值