Извлечь, если строка содержит шаблон чисел - PullRequest
0 голосов
/ 10 ноября 2019

В моем наборе данных есть столбец, в котором я хочу извлечь числа в определенном месте ТОЛЬКО ЕСЛИ структура строки содержит #-#-#.

Как бы я написал это в SQL (в настоящее время пишет в снежинке)?

Пример:

Column_A
abc-net-met-1234-12345-431-5968
abc-eme-ejt-emdn-1948-192
jen-mdk-ent-193-102-1029398
loe-ekd-12-49-nfm

Я хочу, чтобы мой ожидаемый результат был:

Column_A                            Number1    Number2    Number3   Number4
abc-net-met-1234-12345-431-5968        1234      12345        431      5968
abc-eme-ejt-emdn-1948-192              NULL       NULL       NULL      NULL            
jen-mdk-ent-193-102-1029398             193        102    1029398      NULL
loe-ekd-12-49-nfm                      NULL       NULL       NULL      NULL

Я думаю, что это будет что-то вроде этого, но возникнут проблемы:

CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 4) ELSE NULL END Number1
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 5) ELSE NULL END Number2
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 6) ELSE NULL END Number3
CASE WHEN COLUMN_A LIKE '%#-#-#%' THEN SPLIT_PART(COLUMN_A, '-', 7) ELSE NULL END Number4

Ответы [ 3 ]

1 голос
/ 10 ноября 2019

Я не уверен, почему текущий «правильный ответ» помечен как таковой, потому что, хотя он выбирает правильные строки, он не извлекает результат каким-либо особенно полезным способом.

Следующий запросдает правильный ответ, сначала извлекая подстроку, содержащую не менее 3 последовательных чисел, а затем извлекая n-е число из этой подстроки из 3+ чисел:

WITH TEST_TAB AS (SELECT * FROM (VALUES
    ('abc-net-met-1234-12345-431-5968'), ('abc-eme-ejt-emdn-1948-192'),
    ('jen-mdk-ent-193-102-1029398'),     ('loe-ekd-12-49-nfm')
  ) T(COLUMN_A))
SELECT COLUMN_A,
  REGEXP_SUBSTR(REGEXP_SUBSTR('-'||COLUMN_A||'-', '(-\\d+){3,}-'), '\\d+', 2, 1) Number1,
  REGEXP_SUBSTR(REGEXP_SUBSTR('-'||COLUMN_A||'-', '(-\\d+){3,}-'), '\\d+', 2, 2) Number2,
  REGEXP_SUBSTR(REGEXP_SUBSTR('-'||COLUMN_A||'-', '(-\\d+){3,}-'), '\\d+', 2, 3) Number3,
  REGEXP_SUBSTR(REGEXP_SUBSTR('-'||COLUMN_A||'-', '(-\\d+){3,}-'), '\\d+', 2, 4) Number4
FROM TEST_TAB;
1 голос
/ 10 ноября 2019

Я думаю, что ваше like выражение слишком широкое. Вы можете сузить его с помощью соответствия регулярному выражению, например:

CASE 
    WHEN COLUMN_A RLIKE '.*(^|-)[0-9]+-[0-9]+-[0-9]+($|-).*' 
    THEN SPLIT_PART(COLUMN_A, '-', 4) 
    ELSE NULL 
END Number1

Регулярное выражение соответствует 3 последовательным группам цифр, разделенных штрихами и начинающихся с тире (или расположенных в начале строки), илисопровождаемый чертой (или расположенный в конце строки).

Это также может быть написано:

CASE 
    WHEN COLUMN_A RLIKE '.*(^|-)\\d+-\\d+-\\d+($|-).*' 
    THEN SPLIT_PART(COLUMN_A, '-', 4) 
    ELSE NULL 
END Number1
0 голосов
/ 10 ноября 2019

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

Iнет снежинки под рукой для тестирования, но что-то вроде этого:

select column_a,
       max(case when seqnum = 1 then value end) as number_1,
       max(case when seqnum = 2 then value end) as number_2,
       max(case when seqnum = 3 then value end) as number_3,
       max(case when seqnum = 4 then value end) as number_4
from (select t.column_a, s.*,
             row_number() over (partition by (case when s.value rlike '^[0-9]+$'
                                                   then 1 else 0
                                              end)
                                              order by s.index
                               ) as seqnum
      from t cross join lateral
           split_to_table(t.column_a, '-') s
     ) t
group by column_a;
...