根据值列表查询子字符串

时间:2016-07-14 16:31:47

标签: sql oracle parsing

我是从数据集中读取的,但遗憾的是我没有权限进行修改。它连接了值的字符串,我想选择任何这些子串(由给定字符拆分)与特定列表中的任何值匹配的记录。我将通过Python传递查询,因此不能将其与静态列表进行比较。

例如,表格如下:

CrappyColumn
-----------
1;2
4
1
2;1
1;3
2

我可能想要返回其中包含2或4的内容。所以,我的结果应该是:

1;2
4
2
2;1

我玩过regexp_substr并获得了实际可行的东西;然而,当我在完整数据集上运行它时,它只是无限期地运行(在我放弃之前多达10分钟)(它只包含大约三千条记录,其值通常为几百个字符)。我需要能在合理的时间内重复执行的东西。

我意识到 - 即使使用变量比较列表 - 我可以编写我的Python代码来解析列表并构造多个LIKE语句,但这似乎效率低下,我认为有更好的方法

这就是我所做的,花了太长时间:

SELECT DISTINCT CrappyColumn
   FROM 
     (SELECT DISTINCT CrappyColumn, regexp_substr(CrappyColumn, '[^;]+', 1, LEVEL) as UGH
          FROM CrappyTable
CONNECT BY regexp_substr(CrappyColumn, '[^;]+', 1, LEVEL) IS NOT NULL)
WHERE UGH IN ('2', '4')

是否有更好,更快,更清洁的方法来实现这一目标?

编辑 - 决议:

感谢vkp的帮助,以下是我实施的内容:

regexp_like(SITE_ID, '^(2|4)(:)|(:)(2|4)(:)|(:)(2|4)$|^(2|4)$')

我为最终产品修改了它,以便它可以处理多个字符的字符串 - 将[2|4]更改为(2|4)。这适用于搜索不是单个数字的数字的情况。

3 个答案:

答案 0 :(得分:3)

您可以使用like

select t.*
from crappytable t
where ';' || crappycolumn || ';' like '%;2;%' or
      ';' || crappycolumn || ';' like '%;4;%';

您似乎知道将值列表存储在一个列中是一个坏主意,所以我将放弃讨论;)

编辑:

如果您不喜欢like,可以像这样使用regexp_like()

where regexp_like(';' || crappycolumn || ';', ';2;|;4;')

答案 1 :(得分:1)

更简单的方法是使用regexp_like检查列表中是否包含24

select *
from tablename
where regexp_like(crappycolumn,'^[2|4][^0-9]|[^0-9][2|4][^0-9]|[^0-9][2|4]$|^[2|4]$')
  • ^[2|4][^0-9] - 以2或4开头,后面没有数字。
  • [^0-9][2|4][^0-9] - 2或4未成功或前面有数字。
  • [^0-9][2|4]$ - 以2或4结尾,前面没有数字。
  • ^[2|4]$ - 2或4是字符串中唯一的字符。

答案 2 :(得分:0)

另一种形式的regexp_like()。这个正则表达式仅在行的开头或分号后面跟着一个分号或行的末尾时才查找2或4:

SQL> with crappy_tbl(crappy_col) as (
     select '1;2' from dual union
     select '4' from dual union
     select '1' from dual union
     select '2;1' from dual union
     select '1;3' from dual union
     select '2' from dual union
     select '22;;44;' from dual
   )
   select crappy_col
   from crappy_tbl
   where regexp_like(crappy_col, '(^|;)(2|4)(;|$)');

CRAPPY_
-------
1;2
2
2;1
4

SQL>