Запрос для сбора последнего вхождения символа в строку (SQL Progress OpenEdge) - PullRequest
0 голосов
/ 10 октября 2018

Мне нужно выбрать какую-нибудь строку из строки, которая варьируется по длине.Конечным результатом является выбор номера идентификатора, заключенного в скобки, из строки.

Пример данных:

Jones (4)
Smith (Deceased) (100)

Результат из приведенного выше примера долженбыть:

4
100

В идеале я хочу запрос, который найдет начальную позицию последней открытой скобки и заберет данные с этой точки и далее, потому что номер идентификатора, содержащийся в скобках, всегда находится наend.

К сожалению, REVERSE, CHARINDEX и PATINDEX недоступны в OpenEdge функциях 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.

Ниже приведен списоккоманды / функции SQLs доступно для меня:

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

Ответы [ 3 ]

0 голосов
/ 11 октября 2018
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

Или вы можете продлить эту мерзость: -)

0 голосов
/ 11 октября 2018

Или - повторное посещение 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, чтобы соответствовать вашим требованиям, и остерегайтесь крайних случаев (без идентификатора вскобок).

0 голосов
/ 11 октября 2018
select 
  contact_data, 
  rtrim( 
    ltrim( 
      lower( contact_data ), 
      'abcdefghijlmnopqrstuvwxyz( )' 
    ), 
    ')'
  )
from pub.contacts

Скорее волосатый и непременно доставит неприятности.Возможно, вам придется расширить обрезанные символы, этого было достаточно для ваших примеров.Кроме того, если текст перед идентификатором содержит число, оно будет разбито.

В ABL R-INDEX легко решит проблему, однако в синтаксисе SQL отсутствуют некоторые функции обработки строк.

...