redshift regex получает несколько совпадений и расширяет строки - PullRequest
0 голосов
/ 29 ноября 2018

Я работаю над извлечением URL в AWS Redshift.Столбец URL выглядит следующим образом:

url                       item     origin
http://B123//ajdsb        apple    US
http://BYHG//B123         banana   UK
http://B325//BF89//BY85   candy    CA

В результате я хочу получить серию, начинающуюся с B, а также развернуть строки, если в URL есть несколько рядов.

extracted    item     origin
B123         apple    US
BYHG         banana   UK
B123         banana   UK
B325         candy    CA
BF89         candy    CA
BY85         candy    CA

Мой текущий код:

select REGEXP_SUBSTR(url, '(B[0-9A-Z]{3})') as extracted, item, origin
from data

Регулярное выражение работает хорошо, но у меня проблемы с извлечением нескольких значений и расширением их до новых строк.Я пытался использовать REGEXP_MATCHES(url, '(B[0-9A-Z]{3})', 'g'), но функция regexp_matches не существует в Redshift ...

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019
Ответ

IronFarm вдохновил меня, хотя я хотел найти решение, не требующее перекрестного соединения.Вот что я придумал:

with 

-- raw data
src as (
  select 
    1 as id,
    'abc def ghi' as stuff
  union all 
  select
    2 as id,
    'qwe rty' as stuff
),

-- for each id, get a series of indexes for
-- each match in the string
match_idxs as (
  select
    id,
    generate_series(1, regexp_count(stuff, '[a-z]{3}')) as idx
  from
    src
)

select 
  src.id,
  match_idxs.idx,
  regexp_substr(src.stuff, '[a-z]{3}', 1, match_idxs.idx) as stuff_match
from 
  src 
  join match_idxs using (id)
order by 
  id, idx
;

Это дает:

 id | idx | stuff_match
----+-----+-------------
  1 |   1 | abc
  1 |   2 | def
  1 |   3 | ghi
  2 |   1 | qwe
  2 |   2 | rty
(5 rows)
0 голосов
/ 03 декабря 2018

Решение, которое я использую, довольно некрасиво, но достигает желаемых результатов.Он включает использование REGEXP_COUNT для определения максимального числа совпадений в строке, а затем объединение результирующей таблицы чисел с запросом, используя REGEXP_SUBSTR.

-- Get a table with the count of matches
-- e.g. if one row has 5 matches this query will return 0, 1, 2, 3, 4, 5
WITH n_table AS (
    SELECT
        DISTINCT REGEXP_COUNT(url, '(B[0-9A-Z]{3})') AS n
    FROM data
)
-- Join the previous table to the data table and use n in the REGEXP_SUBSTR call to get the nth match
SELECT
    REGEXP_SUBSTR(url, '(B[0-9A-Z]{3})', 1, n) AS extracted,
    item,
    origin
FROM data,
     n_table
-- Only keep non-null matches
WHERE n > 0
  AND REGEXP_COUNT(url, '(B[0-9A-Z]{3})') >= N
...