如果字符串包含数字模式则提取
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;
我的数据集中有一列,我想在其中提取特定位置的数字仅当 字符串结构包含#-#-#
时。
我如何在 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;