查询以收集字符串中最后一次出现的字符(SQL Progress OpenEdge)

Query to collect last occurrence of a character in a string (SQL Progress OpenEdge)

我需要从长度不同的字符串中挑选出一些字符串。 最终结果是从一个字符串中挑出括号中的id号。

数据示例为:

Jones (4)
Smith (Deceased) (100)

上述示例的结果需要是:

4
100

理想情况下,我想要一个查询,它会找到最后一个左括号的开始位置,并从该点开始获取数据,因为包含在括号中的 ID 号始终在末尾。

不幸的是,REVERSECHARINDEXPATINDEXOpenEdge SQL 函数中不可用,因此我无法使用它们。

INSTR(contact_data,'(',1,2) 给了我起点,但要求我提供第 n 次出现 - 这是一个变量,因为有些数据包含 1 个括号,有些包含更多。

我曾尝试将变量引入事件中,但它出错了 - 请参阅下文,如果可以的话请提供帮助!

SELECT * FROM OPENQUERY(PROCLAIM,'
SELECT a.contact_data,
INSTR(a.contact_data,''('',1,a.bracket_occurrences) AS searching_for_start_point,    SUBSTRING(a.contact_data,LOCATE(''('',a.contact_data,1)+1,LENGTH(a.contact_data)-LOCATE(''('',a.contact_data,1)-1) AS contact_id
FROM(
SELECT contact_data,
CAST(LENGTH(contact_data) - LENGTH(REPLACE(contact_data,''('','''')) AS INT) AS bracket_occurrences
FROM PUB.contacts
) AS a
')

不幸的是,我只能使用非常有限的一组 SQL 命令,因为我正在使用 Progress OpenEdge.

下面是我可用的 SQL commands/functions 列表:

ABS,  ACOS,  ADD_MONTHS,  ASCII,  ASIN,  ATAN,  ATAN2,  AVG,  CASE,  CAST,  
CDC_get_changed_columns,  CDC_is_column_changed,  CEILING,  CHAR,  CHR,              
COALESCE,  CONCAT,  CONVERT (ODBC compatible),  CONVERT (Progress extension),  
COS,  COUNT,  CURDATE,  CURTIME,  CURRVAL,  DATABASE,  DAYNAME,  DAYOFMONTH,  
DAYOFWEEK,  DAYOFYEAR,  DB_NAME,  DECODE,  DEGREES,  EXP,  FLOOR,  GREATEST,  
HOUR,  IFNULL,  INITCAP,  INSERT,  INSTR,  LAST_DAY,  LCASE,  LEAST,  LEFT,  
LENGTH,  LOCATE,  LOG10,  LOWER,  LPAD,  LTRIM,  MAX,  MIN,  MINUTE,  MOD,  
MONTH,  MONTHNAME,  MONTHS_BETWEEN,  NEXT_DAY,  NEXTVAL,  NOW,  NULLIF,  NVL,  
PI,  POWER,  PREFIX,  PRO_ARR_DESCAPE function,  PRO_ARR_ESCAPE function,  
PRO_ELEMENT function,  QUARTER,  RADIANS,  RAND,  REPEAT,  REPLACE,  RIGHT,  
ROUND,  ROWID,  RPAD,  RTRIM,  SECOND,  SIGN,  SIN,  SQRT,  SUBSTR,  SUBSTRING 
(ODBC compatible),  SUFFIX,  SUM,  SYSDATE,  SYSTIME,  SYSTIMESTAMP,  TAN,  
TO_CHAR,  TO_DATE,  TO_NUMBER,  TO_TIME,  TO_TIMESTAMP,  TRANSLATE,  UCASE,  
UPPER,  USER,  WEEK,  YEAR
select 
  contact_data, 
  rtrim( 
    ltrim( 
      lower( contact_data ), 
      'abcdefghijlmnopqrstuvwxyz( )' 
    ), 
    ')'
  )
from pub.contacts

毛茸茸的,肯定会惹麻烦。您可能需要扩展修剪后的字符,这对您的示例来说已经足够了。此外,如果 ID 之前的文本包含数字,它将中断。

在 ABL 中,R-INDEX 可以轻松解决这个问题,但是 SQL 语法缺少一些字符串操作函数。

select 
  contact_data, 
  rtrim(
    substring (
      contact_data,
      case
        when substring( contact_data, length( contact_data ) - 2, 1 ) = '(' then length( contact_data ) -1 
        when substring( contact_data, length( contact_data ) - 3, 1 ) = '(' then length( contact_data ) -2
        when substring( contact_data, length( contact_data ) - 4, 1 ) = '(' then length( contact_data ) -3
        when substring( contact_data, length( contact_data ) - 5, 1 ) = '(' then length( contact_data ) -4
        when substring( contact_data, length( contact_data ) - 6, 1 ) = '(' then length( contact_data ) -5
        when substring( contact_data, length( contact_data ) - 7, 1 ) = '(' then length( contact_data ) -6
        when substring( contact_data, length( contact_data ) - 8, 1 ) = '(' then length( contact_data ) -7
        else -1
      end
    ), 
    ')'
  )
from pub.contacts

或者你可以扩展这个可憎的东西:-)

或者——重温INSTR(我很少用SQL,所以这是一个学习经验):

select 
  contact_data, 
  rtrim(
    substring (
      contact_data,
      greatest( 
        instr( contact_data, '(', 1, 1 ), 
        instr( contact_data, '(', 1, 2 ), 
        instr( contact_data, '(', 1, 3 ) 
      ) + 1
    ), 
    ')'
  )
from pub.contacts

再次扩展 instr 以满足您的要求并提防边缘情况(括号中没有 ID)。