根据字符串的条件取值权
Based on Condition Extract Values Right of String
我在 sql 中有一个数据集,如下所示:
Col1 Col2
13_DND_ 5
_DND_ 6
123_ETL_ 10
ETL_ 12
DND_ 15
_ETL_ 17
如果 Col1 包含 _DND_
或 _ETL_
,我想删除 DND_
和 ETL_
左侧的所有内容。
最终预期输出如下:
Col1 Col2 Col3
13_DND_456 5 DND_456
_DND_de1f 6 DND_de1f
123_ETL_mene 10 ETL_mene
ETL_test 12 ETL_test
DND_se 15 DND_se
_ETL_def_ 17 ETL_def_
我在下面尝试了 1 个条件,但结果为 NULL:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%'
THEN RIGHT(Col1, LENGTH(Col1) - CHARINDEX('DND_', Col1)) ELSE Col1 END Col3;
我倾向于使用 STUFF()
:
select (case when col1 like '%[_]DND%'
then stuff(col1, 1, charindex('_DND', col1) - 1, '')
when col1 like '%[_]END%'
then stuff(col1, 1, charindex('_END', col1) - 1, '')
else col1
end) as col3
您的代码不起作用,因为 LIKE
失败,除非 "DND" 从第二个位置开始。所以,它返回 NULL
.
因为 _
是 LIKE
中的通配符,LIKE
模式将其转义。
您忘记在 LIKE 中使用通配符。
而不是这个:
SELECT *, CASE WHEN Col1 LIKE '_DND_'
你想要这个:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%'
这适合我的需要:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%' OR Col1 LIKE '%_ETL_%'
THEN RIGHT(Col1, length(Col1) - charindex('-', Col1)) ELSE Col1 END Col3 FROM DF;
我能想到的最短的就是 REGEXP_REPLACE
:
select col1, regexp_replace(col1, '.*_(ETL|DND)_', '\1_') from x;
--------------+-----------------------------------------------+
COL1 | REGEXP_REPLACE(COL1, '.*_(ETL|DND)_', '\1_') |
--------------+-----------------------------------------------+
13_DND_456 | DND_456 |
345DND_7658 | 345DND_7658 |
123_ETL_mene | ETL_mene |
_ETL_def_ | ETL_def_ |
123ETL_mene | 123ETL_mene |
--------------+-----------------------------------------------+
--------------+-----------------------------------------+
基于 Gordon 的回答:
select col1, (case when col1 like '%^_DND%' escape '^'
then substr(col1, charindex('_DND', col1) + 1)
when col1 like '%^_END%' escape '^'
then substr(col1, charindex('_END', col1) + 1)
else col1
end) as col3 from x;
--------------+--------------+
COL1 | COL3 |
--------------+--------------+
13_DND_456 | DND_456 |
345DND_7658 | 345DND_7658 |
123_ETL_mene | 123_ETL_mene |
_ETL_def_ | _ETL_def_ |
123ETL_mene | 123ETL_mene |
--------------+--------------+
我在 sql 中有一个数据集,如下所示:
Col1 Col2
13_DND_ 5
_DND_ 6
123_ETL_ 10
ETL_ 12
DND_ 15
_ETL_ 17
如果 Col1 包含 _DND_
或 _ETL_
,我想删除 DND_
和 ETL_
左侧的所有内容。
最终预期输出如下:
Col1 Col2 Col3
13_DND_456 5 DND_456
_DND_de1f 6 DND_de1f
123_ETL_mene 10 ETL_mene
ETL_test 12 ETL_test
DND_se 15 DND_se
_ETL_def_ 17 ETL_def_
我在下面尝试了 1 个条件,但结果为 NULL:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%'
THEN RIGHT(Col1, LENGTH(Col1) - CHARINDEX('DND_', Col1)) ELSE Col1 END Col3;
我倾向于使用 STUFF()
:
select (case when col1 like '%[_]DND%'
then stuff(col1, 1, charindex('_DND', col1) - 1, '')
when col1 like '%[_]END%'
then stuff(col1, 1, charindex('_END', col1) - 1, '')
else col1
end) as col3
您的代码不起作用,因为 LIKE
失败,除非 "DND" 从第二个位置开始。所以,它返回 NULL
.
因为 _
是 LIKE
中的通配符,LIKE
模式将其转义。
您忘记在 LIKE 中使用通配符。
而不是这个:
SELECT *, CASE WHEN Col1 LIKE '_DND_'
你想要这个:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%'
这适合我的需要:
SELECT *, CASE WHEN Col1 LIKE '%_DND_%' OR Col1 LIKE '%_ETL_%'
THEN RIGHT(Col1, length(Col1) - charindex('-', Col1)) ELSE Col1 END Col3 FROM DF;
我能想到的最短的就是 REGEXP_REPLACE
:
select col1, regexp_replace(col1, '.*_(ETL|DND)_', '\1_') from x;
--------------+-----------------------------------------------+
COL1 | REGEXP_REPLACE(COL1, '.*_(ETL|DND)_', '\1_') |
--------------+-----------------------------------------------+
13_DND_456 | DND_456 |
345DND_7658 | 345DND_7658 |
123_ETL_mene | ETL_mene |
_ETL_def_ | ETL_def_ |
123ETL_mene | 123ETL_mene |
--------------+-----------------------------------------------+
--------------+-----------------------------------------+
基于 Gordon 的回答:
select col1, (case when col1 like '%^_DND%' escape '^'
then substr(col1, charindex('_DND', col1) + 1)
when col1 like '%^_END%' escape '^'
then substr(col1, charindex('_END', col1) + 1)
else col1
end) as col3 from x;
--------------+--------------+
COL1 | COL3 |
--------------+--------------+
13_DND_456 | DND_456 |
345DND_7658 | 345DND_7658 |
123_ETL_mene | 123_ETL_mene |
_ETL_def_ | _ETL_def_ |
123ETL_mene | 123ETL_mene |
--------------+--------------+