Выберите строки, в которых первый, последний или оба символа являются специальными или пунктуацией, если только они не имеют точку в конце - PullRequest
2 голосов
/ 04 апреля 2019

Мне нужно извлечь строки из моей таблицы, имена которых начинаются или заканчиваются [:space:] или другим специальным символом [:punct:], исключая одну точку (.) в конце имени.Идея состоит в том, чтобы извлечь имена, которые являются возможными несоответствиями.

Примеры, которые должны появиться:

  1. 'GEORGE & SON ' - имеет дополнительный пробел в конце.
  2. '-GEORGE & SON' - имеет дополнительный - в начале.
  3. '&GEORGE & SON' - имеет дополнительный & в начале.
  4. '-GEORGE & SON S.A.' - имеет дополнительный - вначало.Точка . в конце не является проблемой.
  5. 'GEORGE & SON..' - имеет не одну, а две точки в конце.Это исключение для строк, которые заканчиваются более чем одним .;они также являются дурными именами.

примеры, которые не должны появляться:

  1. 'GEORGE & SON.' - в конце есть только дополнительный '.'.

Я использую выражение:

REGEXP_LIKE(col, '(^[[:punct:]]|[[:punct:]]$)|(^[[:space:]]|[[:space:]]$)')

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

Как я могу изменить это, чтобы получить нужный мне результат?

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Поскольку заранее определенный класс символов пунктуации не работает для конца строки, вместо него используется собственный класс символов.Оставляя точку намеренно.Добавление в одиночную кавычку отдельно (поскольку экранирование не сработало, и в этом случае может быть сложно найти правильный символ для оператора q ).Добавление закрывающей квадратной скобки само по себе, так как Oracle, кажется, не справляется с этим правильно при выходе из него.Наконец, добавление завершающих последовательных точек в явном виде:

WITH T (id, col) AS (
  SELECT 1, 'GEORGE & SON ' FROM DUAL UNION ALL
  SELECT 2, '-GEORGE & SON'  FROM DUAL UNION ALL
  SELECT 3, '&GEORGE & SON'  FROM DUAL UNION ALL
  SELECT 4, 'GEORGE & SON..'  FROM DUAL UNION ALL
  SELECT 5, 'GEORGE & SON.'  FROM DUAL UNION ALL
  SELECT 6, '-GEORGE & SON S.A.' FROM DUAL UNION ALL
  SELECT 7, 'GEORGE & SON!' FROM DUAL UNION ALL
  SELECT 8, 'GEORGE & SON"' FROM DUAL UNION ALL
  SELECT 9, 'GEORGE & SON#' FROM DUAL UNION ALL
  SELECT 10, 'GEORGE & SON$' FROM DUAL UNION ALL
  SELECT 11, 'GEORGE & SON%' FROM DUAL UNION ALL
  SELECT 12, 'GEORGE & SON&' FROM DUAL UNION ALL
  SELECT 13, 'GEORGE & SON(' FROM DUAL UNION ALL
  SELECT 14, 'GEORGE & SON)' FROM DUAL UNION ALL
  SELECT 15, 'GEORGE & SON*' FROM DUAL UNION ALL
  SELECT 16, 'GEORGE & SON+' FROM DUAL UNION ALL
  SELECT 17, 'GEORGE & SON,' FROM DUAL UNION ALL
  SELECT 18, 'GEORGE & SON\' FROM DUAL UNION ALL
  SELECT 19, 'GEORGE & SON-' FROM DUAL UNION ALL
  SELECT 20, 'GEORGE & SON\' FROM DUAL UNION ALL
  SELECT 21, 'GEORGE & SON/' FROM DUAL UNION ALL
  SELECT 22, 'GEORGE & SON:' FROM DUAL UNION ALL
  SELECT 23, 'GEORGE & SON;' FROM DUAL UNION ALL
  SELECT 24, 'GEORGE & SON<' FROM DUAL UNION ALL
  SELECT 25, 'GEORGE & SON=' FROM DUAL UNION ALL
  SELECT 26, 'GEORGE & SON>' FROM DUAL UNION ALL
  SELECT 27, 'GEORGE & SON?' FROM DUAL UNION ALL
  SELECT 28, 'GEORGE & SON@' FROM DUAL UNION ALL
  SELECT 29, 'GEORGE & SON[' FROM DUAL UNION ALL
  SELECT 30, 'GEORGE & SON^' FROM DUAL UNION ALL
  SELECT 31, 'GEORGE & SON_' FROM DUAL UNION ALL
  SELECT 32, 'GEORGE & SON`' FROM DUAL UNION ALL
  SELECT 33, 'GEORGE & SON{' FROM DUAL UNION ALL
  SELECT 34, 'GEORGE & SON|' FROM DUAL UNION ALL
  SELECT 35, 'GEORGE & SON}' FROM DUAL UNION ALL
  SELECT 36, 'GEORGE & SON~' FROM DUAL UNION ALL
  SELECT 37, 'GEORGE & SON''' FROM DUAL UNION ALL
  SELECT 38, 'GEORGE & SON]' FROM DUAL)
SELECT
  * FROM T
 WHERE REGEXP_LIKE(col, '(^[[:punct:]]|[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']$)|]$|\.\.$|(^[[:space:]]|[[:space:]]$)')
 ORDER BY id
;

Обновленные требования

Знаки пунктуации с последующей точкой

Добавление дополнительной точки в набор специальных символов;переходя от

'[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']$'

к

'[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']\.?$'

как в

WITH T (id, col) AS (
  SELECT 40, 'GEORGE & SON^.'FROM DUAL UNION ALL
  SELECT 41, 'GEORGE & SON_.'FROM DUAL UNION ALL
  SELECT 42, 'GEORGE & SON`.'FROM DUAL UNION ALL
  SELECT 43, 'GEORGE & SON{.'FROM DUAL UNION ALL
  SELECT 44, 'GEORGE & SON|.'FROM DUAL UNION ALL
  SELECT 45, 'GEORGE & SON}.'FROM DUAL UNION ALL
  SELECT 46, 'GEORGE & SON~.'FROM DUAL UNION ALL
  SELECT 47, 'GEORGE & SON''.'FROM DUAL UNION ALL
  SELECT 48, 'GEORGE & SON].'FROM DUAL)
SELECT
  * FROM T
 WHERE REGEXP_LIKE(col, '([-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']\.?$)|]\.?$')
 ORDER BY id
;

Повторение (комбинаций) пробелов и специальных символов в строке

Первоначально запрашивались только начальные и конечные вхождения…; -)

Последовательности из двух или более символов пробела / пунктуации перехватываются

[[:space:][:punct:]]{2,}

Если вы хотите это явно внутри строк,only - окружить их символами слова:

\w[[:space:][:punct:]]{2,}\w

Начальные / завершающие последовательные пробелы уже сопоставлены, когда найден один - нет необходимости беспокоиться о них явно.
Что дает:

WITH T (id, col) AS (
  SELECT 50, 'GEORGE & SON  ' FROM DUAL UNION ALL
  SELECT 51, 'GEORGE & SON   '  FROM DUAL UNION ALL
  SELECT 52, '  GEORGE & SON'  FROM DUAL UNION ALL
  SELECT 53, '    GEORGE & SON'  FROM DUAL UNION ALL
  SELECT 54, 'GEORGE &  SON'  FROM DUAL UNION ALL
  SELECT 55, 'GEORGE  & SON S.A.' FROM DUAL UNION ALL
  SELECT 56, 'GEORGE & SON    S.A.' FROM DUAL UNION ALL
  SELECT 60, '  GEORGE and SON'  FROM DUAL UNION ALL
  SELECT 61, ' ,GEORGE and SON' FROM DUAL UNION ALL
  SELECT 62, ', GEORGE and SON'  FROM DUAL UNION ALL
  SELECT 63, 'GEORGE -- SON' FROM DUAL UNION ALL
  SELECT 64, 'GEORGE --SON' FROM DUAL UNION ALL
  SELECT 65, 'GEORGE & SON' FROM DUAL UNION ALL
  SELECT 66, 'GEORGE + SON' FROM DUAL UNION ALL
  SELECT 67, 'GEORGE and  , SON' FROM DUAL UNION ALL
  SELECT 68, 'GEORGE and , SON' FROM DUAL UNION ALL
  SELECT 69, 'GEORGE and SON ,'  FROM DUAL UNION ALL
  SELECT 70, 'GEORGE and SON. '  FROM DUAL UNION ALL
  SELECT 71, 'GEORGE and+-SON'  FROM DUAL)
SELECT
  * FROM T
--  WHERE REGEXP_LIKE(col, '(^[[:punct:]]|[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']\.?$)|]$|\.\.$|(^[[:space:]]|[[:space:]]$)|[[:space:][:punct:]]{2,}')
  WHERE REGEXP_LIKE(col, '(^[[:punct:]]|[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']\.?$)|]$|\.\.$|(^[[:space:]]|[[:space:]]$)|\w[[:space:][:punct:]]{2,}\w')
  ORDER BY id
;

Но это даст ложные срабатывания, наиболее заметно GEORGE & SON .Этого можно в некоторой степени избежать, заменив [: punct:] менее инклюзивным набором.(Окончательный) выбор будет зависеть от того, являются ли ложные отрицания или ложные срабатывания более значимыми.

См. Это в действии:

Поймать произвольные последовательности знаков пунктуации и пробела - но допускается одиночные буквы, за которыми следуют одна точка и один пробел

Как упоминалось ранее, ложные срабатывания должны быть сбалансированы с ложными отрицаниями.Так или другой.Тем не менее, сейчас, вероятно, самое время подумать о том, чтобы разбить общую проблему на более мелкие и заняться ими индивидуально.Даже если GEORGE и P. SON вполне приемлемы, вы, вероятно, захотите просмотреть, например, -GEORGE и P. SON .Итак, давайте сосредоточимся на последовательностях случайных символов в середине строки - даже вспоминая ** и ** ранее и допуская перечисления (и, следовательно, запятые):

WHERE
  REGEXP_LIKE(col, '\w[[:space:][:punct:]]{2,}\w')
  AND
  NOT REGEXP_LIKE(col, ' [[:upper:]]\. \w')
  AND
  NOT INSTR(col, ', ') > 0
  AND
  NOT INSTR(col, ' & ') > 0

Возможно, за которыми следует

  WHERE
  REGEXP_LIKE(col, '\w[[:space:][:punct:]]{2,}\w')
  AND
  (REGEXP_LIKE(col, ' [[:upper:]]\. \w')
   OR
   INSTR(col, ', ') > 0
   OR
   INSTR(col, ' & ') > 0
  )

, чтобы найти, например, GEORGE и SON между многими действительными.INSTR может быть быстрее, чем REGEX - в зависимости от общих обстоятельств ...

Еще несколько слов о механике

(i) [[: punct:] [: space:]] по существу объединяет [[: punct:]] и [[: space:]] в один класс символов.Что касается выбора из этого класса, то порядок не имеет значения.

(ii)

[-!"#$%&()*+,\/:;<=>?@[^_`{|}~' || '''' || ']

равно

[-!"#$%&()*+,\/:;<=>?@[^_`{|}~]

с добавлением одной цитаты,Если бы это было выполнено напрямую, Oracle рассмотрел бы одинарную кавычку для завершения значения параметра.А экранирование одинарной кавычки с обратной косой чертой не сработало ... Так что, по сути, это то, что было названо выше «Добавление в одиночную кавычку отдельно».

Пожалуйста, прокомментируйте, если и как это требует корректировки / более подробно.

0 голосов
/ 04 апреля 2019

просто добавьте {2} после второго [[:punct:]]. это означает, что точка должна быть там как минимум 2 раза

with tab as(
  select 'GEORGE & SON ' as s from dual union all
  select '-GEORGE & SON'  as s from dual union all
  select '&GEORGE & SON'  as s from dual union all
  select 'GEORGE & SON..'  as s from dual union all
  select 'GEORGE & SON.'  as s from dual union all
  select '-GEORGE & SON S.A.' as s from dual  
)
select * from  tab 
where REGEXP_LIKE(s, '(^[[:punct:]]|[[:punct:]]{2}$)|(^[[:space:]]|[[:space:]]$)') 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...