如何选择包含特定子字符串的单词列表作为 SQL 查询(oracle)的一部分?

Posted

技术标签:

【中文标题】如何选择包含特定子字符串的单词列表作为 SQL 查询(oracle)的一部分?【英文标题】:How to select the list of words containing a particular substring as part of a SQL query (oracle)? 【发布时间】:2019-12-13 19:54:05 【问题描述】:

我正在尝试返回包含字符串中某个子字符串的“单词”列表(以空格分隔),作为 Oracle Sql 查询的一部分。想要以逗号分隔列表的形式返回结果。每个匹配的单独行也可以。

[text_col] 字段中的示例字符串:

一些词 123-asdf-789A 和这个 456-asdf-555A 更多的词等等。

想要的结果:123-asdf-789A, 456-asdf-555A

这是我目前所拥有的,但它只返回第一个结果,而且它是两个单独的正则表达式这一事实使得我很难像我想要的那样连接所有匹配项。

CONCAT(REGEXP_SUBSTR(text_col, ''(([^[:space:]]+)\asdf)'', 1, 1, ''i'', 1), 
REGEXP_SUBSTR(text_col, ''\asdf([^[:space:]]+)'', 1, 1, ''i'', 1))

【问题讨论】:

【参考方案1】:

您可以将一些正则表达式函数一起使用:

with tab(str) as
(
 select 'some words 123-asdf-789A and also this one 456-asdf-555A more words etc' from dual
), t as 
(
select regexp_substr(str,'[^[:space:]]+',1,level) as str, level as lvl
  from tab
connect by level <= regexp_count(str,'[:space:]')  
)
select listagg(str,',') within group (order by lvl) as "Result"
  from t
 where regexp_like(str,'-');

Result
---------------------------------
123-asdf-789A,456-asdf-555A

Demo

首先用空格分割(通过[:space:]posix)并取出包含破折号的字符,最后通过listagg()函数连接

【讨论】:

【参考方案2】:

使用递归子查询因式分解子句并遍历连接字符串的所有匹配项:

Oracle 设置

CREATE TABLE test_data ( value ) AS
SELECT 'some words 123-asdf-789A and also this one 456-asdf-555A more words etc.' FROM DUAL UNION ALL
SELECT 'some words without the expected sub-string' FROM DUAL UNION ALL
SELECT 'asdf asdf-123 456-asdf 78-asdf-90' FROM DUAL

查询

WITH matches ( value, idx, cnt, match ) AS (
  SELECT value,
         0,
         REGEXP_COUNT( value, '\S*asdf\S*' ),
         CAST( NULL AS VARCHAR2(4000) )
  FROM   test_data
UNION ALL
  SELECT value,
         idx + 1,
         cnt,
         CASE idx WHEN 0 THEN '' ELSE match || ' ' END
           || REGEXP_SUBSTR( value, '\S*asdf\S*', 1, idx + 1 )
  FROM   matches
  WHERE  idx < cnt
)
SELECT value, match
FROM   matches
WHERE  idx = cnt;

输出

价值 |匹配 :------------------------------------------------- ---------------------- | :-------------------------------- 一些没有预期子字符串的单词 | 一些单词 123-asdf-789A 和这个 456-asdf-555A 更多的单词等等。 123-asdf-789A 456-asdf-555A asdf asdf-123 456-asdf 78-asdf-90 | asdf asdf-123 456-asdf 78-asdf-90

db小提琴here

【讨论】:

以上是关于如何选择包含特定子字符串的单词列表作为 SQL 查询(oracle)的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过特定的字符串元素将字符串列表拆分为字符串的子列表

一道Python练习题引发的,一个知识点的探讨:删除列表中特定元素的几种方法

删除列包含特定子字符串的行[重复]

在特定单词之后从字符串中获取子字符串

是否有一个 SQL 函数可以根据特定列的转换子字符串的计算从数据库中选择样本?

在Python中随机反转列表列表中的一半单词