oracle regex计算一个被逗号包围的字符串的多次出现次数

qojgxg4l  于 2021-08-13  发布在  Java
关注(0)|答案(3)|浏览(504)

这个问题和我先前的一个问题相似。我正在寻找一种方法来计算oracle(11g)sql数据库中列中以逗号分隔的值列表中的字符串。例如,假设我有以下数据:

  1. SELECT ('SL,PK') as col1 FROM dual
  2. UNION ALL
  3. SELECT ('SL,CR,SL') as col1 FROM dual
  4. UNION ALL
  5. SELECT ('PK,SL') as col1 FROM dual
  6. UNION ALL
  7. SELECT ('SL,SL') as col1 FROM dual
  8. UNION ALL
  9. SELECT ('SL') as col1 FROM dual
  10. UNION ALL
  11. SELECT ('PK') as col1 FROM dual
  12. UNION ALL
  13. SELECT ('PI,SL,PK') as col1 FROM dual
  14. UNION ALL
  15. SELECT ('PI,SL,SL,PK') as col1 FROM dual
  16. UNION ALL
  17. SELECT ('PI,SL,SL,SL,PK') as col1 FROM dual
  18. UNION ALL
  19. SELECT ('PI,SL,SL,SL,SL,PK') as col1 FROM dual
  20. UNION ALL
  21. SELECT ('PI,OSL,SL,PK') as col1 FROM dual
  22. UNION ALL
  23. SELECT ('PI,SL,SLR,PK') as col1 FROM dual
  24. COL1
  25. -----
  26. SL,PK
  27. SL,CR,SL
  28. PK,SL
  29. SL,SL
  30. SL
  31. PK
  32. PI,SL,PK
  33. PI,SL,SL,PK
  34. PI,SL,SL,SL,PK
  35. PI,SL,SL,SL,SL,PK
  36. PI,OSL,SL,PK
  37. PI,SL,SLR,PK

我希望严格计算子字符串“sl”的所有出现次数(即不包括“osl”、“slr”等)。理想结果如下:

  1. COL1 COL2
  2. ----- -----
  3. SL,PK 1
  4. SL,CR,SL 2
  5. PK,SL 1
  6. SL,SL 2
  7. SL 1
  8. PK 0
  9. PI,SL,PK 1
  10. PI,SL,SL,PK 2
  11. PI,SL,SL,SL,PK 3
  12. PI,SL,SL,SL,SL,PK 4
  13. PI,OSL,SL,PK 1
  14. PI,SL,SLR,PK 1

我可以用 length 以及 regexp_replace :

  1. SELECT
  2. col1,
  3. (length(col1) - NVL(length(regexp_replace(regexp_replace(col1,'(^|,)(SL)($|,)','\1' || '' || '\3',1,0,'imn'),'(^|,)(SL)($|,)','\1' || '' || '\3',1,0,'imn')),0))/length('SL') as col2
  4. FROM (
  5. SELECT ('SL,PK') as col1 FROM dual
  6. UNION ALL
  7. SELECT ('SL,CR,SL') as col1 FROM dual
  8. UNION ALL
  9. SELECT ('PK,SL') as col1 FROM dual
  10. UNION ALL
  11. SELECT ('SL,SL') as col1 FROM dual
  12. UNION ALL
  13. SELECT ('SL') as col1 FROM dual
  14. UNION ALL
  15. SELECT ('PK') as col1 FROM dual
  16. UNION ALL
  17. SELECT ('PI,SL,PK') as col1 FROM dual
  18. UNION ALL
  19. SELECT ('PI,SL,SL,PK') as col1 FROM dual
  20. UNION ALL
  21. SELECT ('PI,SL,SL,SL,PK') as col1 FROM dual
  22. UNION ALL
  23. SELECT ('PI,SL,SL,SL,SL,PK') as col1 FROM dual
  24. UNION ALL
  25. SELECT ('PI,OSL,SL,PK') as col1 FROM dual
  26. UNION ALL
  27. SELECT ('PI,SL,SLR,PK') as col1 FROM dual
  28. )
  29. COL1 COL2
  30. ----- -----
  31. SL,PK 1
  32. SL,CR,SL 2
  33. PK,SL 1
  34. SL,SL 2
  35. SL 1
  36. PK 0
  37. PI,SL,PK 1
  38. PI,SL,SL,PK 2
  39. PI,SL,SL,SL,PK 3
  40. PI,SL,SL,SL,SL,PK 4
  41. PI,OSL,SL,PK 1
  42. PI,SL,SLR,PK 1

但希望有一个更优雅的解决方案,也许是 regexp_count . 我已经在其他具有单词边界的regex实现中成功地实现了我的目标 \b 构造可用(带 \bSL\b ),但尚未找到针对oracle正则表达式的解决方案。

xurqigkl

xurqigkl1#

你可以用 regexp_count() 如果破解字符串:

  1. select col1, regexp_count(replace(col1, ',', ',,'), '(^|\W)SL(\W|$)')

这将分隔符加倍,这样第一个匹配就不会消耗掉它——绕过了根本的问题,即oracle正则表达式不支持向前看。
这是一把小提琴。

0g0grzrc

0g0grzrc2#

这里有一个选择:

  1. SQL> with temp as
  2. 2 (select col1,
  3. 3 regexp_substr(col1, '[^,]+', 1, column_value) val
  4. 4 from test cross join
  5. 5 table(cast(multiset(select level from dual
  6. 6 connect by level <= regexp_count(col1, ',') + 1
  7. 7 ) as sys.odcinumberlist))
  8. 8 )
  9. 9 select col1,
  10. 10 sum(case when val = 'SL' then 1 else 0 end) col2
  11. 11 From temp
  12. 12 group by col1;
  13. COL1 COL2
  14. ----------------- ----------
  15. PI,SL,SLR,PK 1
  16. PK,SL 1
  17. PK 0
  18. SL,CR,SL 2
  19. PI,OSL,SL,PK 1
  20. SL,SL 2
  21. PI,SL,SL,PK 2
  22. PI,SL,SL,SL,PK 3
  23. SL,PK 1
  24. SL 1
  25. PI,SL,PK 1
  26. PI,SL,SL,SL,SL,PK 4
  27. 12 rows selected.
  28. SQL>

它有什么作用? temp cte将每列拆分为行(分隔符为逗号)
决赛 select 简单地计算 SL 每个都有一个 col1

展开查看全部
w1e3prcc

w1e3prcc3#

你可以使用 XMLTABLE 要将字符串分开然后计数:

  1. SELECT col1,
  2. (
  3. SELECT COUNT(*)
  4. FROM XMLTABLE(
  5. ('"' || REPLACE( col1, ',', '","' ) || '"')
  6. COLUMNS
  7. value CHAR(2) PATH '.'
  8. )
  9. WHERE value = 'SL'
  10. ) AS col2
  11. FROM test_data

因此,对于您的测试数据:

  1. CREATE TABLE test_data ( col1 ) AS
  2. SELECT 'SL,PK' FROM dual UNION ALL
  3. SELECT 'SL,CR,SL' FROM dual UNION ALL
  4. SELECT 'PK,SL' FROM dual UNION ALL
  5. SELECT 'SL,SL' FROM dual UNION ALL
  6. SELECT 'SL' FROM dual UNION ALL
  7. SELECT 'PK' FROM dual UNION ALL
  8. SELECT 'PI,SL,PK' FROM dual UNION ALL
  9. SELECT 'PI,SL,SL,PK' FROM dual UNION ALL
  10. SELECT 'PI,SL,SL,SL,PK' FROM dual UNION ALL
  11. SELECT 'PI,SL,SL,SL,SL,PK' FROM dual UNION ALL
  12. SELECT 'PI,OSL,SL,PK' FROM dual UNION ALL
  13. SELECT 'PI,SL,SLR,PK' FROM dual

这将输出:

  1. COL1 | COL2
  2. :---------------- | ---:
  3. SL,PK | 1
  4. SL,CR,SL | 2
  5. PK,SL | 1
  6. SL,SL | 2
  7. SL | 1
  8. PK | 0
  9. PI,SL,PK | 1
  10. PI,SL,SL,PK | 2
  11. PI,SL,SL,SL,PK | 3
  12. PI,SL,SL,SL,SL,PK | 4
  13. PI,OSL,SL,PK | 1
  14. PI,SL,SLR,PK | 2

db<>在这里摆弄

展开查看全部

相关问题