如果字符串包含数字模式则提取

Extract if string contains numbers pattern

我的数据集中有一列,我想在其中提取特定位置的数字仅当 字符串结构包含#-#-# 时。

我如何在 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

我认为您的 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

我手边没有 Snowflake,但像这样的东西应该有用: 这里是建议的做法:将字符串拆分为table,枚举数字,然后使用条件聚合。

我手头没有 Snowflake 可以测试,但像这样:

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;

我不确定为什么当前的 "correct answer" 被这样标记,因为虽然它选择了正确的行,但它没有以任何特别有用的方式提取结果。

以下查询通过首先提取至少包含 3 个连续数字的子字符串,然后从该 3+ 个数字的子字符串中提取第 n 个数字来提供正确答案:

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;