Oracle SQL 查找字符串并向后工作

Oracle SQL Find A String & Work Backwards

我想做的是在结果中找到一个特定的字符串,然后从该字符串向后工作以获得我需要的内容。举个例子,假设我的结果是 "This thing is heavy at 500KG no matter what"。我想找到 "KG" 然后向后工作以获得“500KG”。

我想从 KG 向后计算的原因是结果可以有不同的字符串,例如 "This thing is heavy at 500 kg" 或“500 - This thing is heavy 500Kg”等。唯一不变的是 KG(即使在它的不同的状态)。

我正在使用 regexp_instr 和 substr 将结果缩小到类似 "This thing is heavy at 500KG" 的范围 - 本质上是找到 KG 并删除它后面的所有内容。

建议?

Oracle 的正则表达式引擎目前不支持先行或后行,因此无法找到您在问题中描述的正确字符串。

话虽如此,您只需使用 REGEXP_SUBSTR() 即可;像下面这样的东西可能会起作用(取决于你的数据):

regexp_substr(str, '\d+\s?kg', 1, 1, 'i')

这将搜索任意数量的数字,后跟可选的 space,再后跟字符串 kg。其他参数是位置(从 1 开始)、出现(第一个)和匹配参数(不区分大小写)。

这会让你得到你想要的:

SQL> with str (s) as (
  2  select 'This thing is heavy at 500 kg'
  3    from dual
  4   union all
  5  select '500 - This thing is heavy 500Kg'
  6    from dual
  7         )
  8  select regexp_substr(s, '\d+\s?kg', 1, 1, 'i')
  9    from str;

REGEXP_SUBSTR(S,'\D+\S?KG',1,1,'I')
---------------------------------------------------
500 kg
500Kg

SQL>

之所以有效,是因为您正在搜索 kg 的号码。因此,如果此字符串后没有数字,则不会返回它。

根据您的数据和您想要的输出,这可能还不够。例如,如果千克也可以表示为 k.g.,并且您想删除数字和大写字符串之间的 space,您可能想要执行如下操作:

SQL> with str (s) as (
  2  select 'This thing is heavy at 6872 kg'
  3    from dual
  4   union all
  5  select '157 - This thing is heavy 248K.g'
  6    from dual
  7         )
  8  select regexp_substr(s, '(\d+)\s?k\.?g', 1, 1, 'i', 1) || 'KG'
  9    from str;

REGEXP_SUBSTR(S,'(\D+)\S?K\.?G',1,1,'I',1)||'KG'
-------------------------------------------------------------------
6872KG
248KG

SQL>

我添加的最后一个参数是要返回的子表达式,由组 (\d+) 标识。这将挑选出第一个(唯一的)子表达式,这将是您的号码并将字符串 KG 连接到该号码的末尾。

如果您使用的是 Oracle 10g,您可以执行以下操作(@Ben 的回答在 11g 或 12c 中工作得很好):

SELECT REGEXP_REPLACE(mystring, '^.*?(\d+)\s*k\.?g.*$', 'KG', 1, 1, 'i')
  FROM mytable

这里不能使用REGEXP_SUBSTR()的原因是这个函数的10g版本中没有最后一个参数(subexpression)

如果你想捕捉各种测量单位,那可能会更困难,但并非不可能,例如:

SELECT REGEXP_REPLACE(mystring, '^.*?(\d+)\s*(k?g|lbs?|oz).*$', '', 1, 1, 'i')
  FROM mytable

这将捕获克 (g)、千克 (kg)、磅 (lblbs) 和盎司 (oz)。