在子字符串中使用charindex来修剪字符串

时间:2015-10-13 13:31:42

标签: sql sql-server tsql sql-server-2012

有一列name,我想用它来制作一个新列。 例如:

name
asd_abceur1mz_a
asd_fxasdrasdusd3mz_a
asd_abceur10yz_a
asd_fxasdrasdusd15yz_a

列的长度不固定所以我假设我必须使用charindex来获得一个可以修剪的参考点。

我想要的是什么:最后始终有z_a,我需要将z_a的左边部分放在一个单独的列中,如下所示:

nameNew
eur1m
usd3m
eur10y
usd15y

问题是数字(在本例中为1,3,10,15)有1位或2位数。我需要从name提取信息到nameNew

之后我想更容易阅读并输出如下:

eur_1m
usd_3m
eur_10y
usd_15y

我尝试使用substring和charindex的组合,但到目前为止还没有成功。

SELECT  *
      , SUBSTRING(name, 1, ( CHARINDEX('z_a', NAME) - 1 )) AS nameNew
FROM    myTable

这是第一步,修剪字符串,第二步(使其更容易阅读)我不知道如何定位数字并放置_。 任何帮助,将不胜感激。使用sql server 2012

编辑:

首先感谢您的时间和解决方案。但是你的查询或多或少,即使它们工作1或2位数也有同样的问题。考虑一下这种情况:

name
ab_dertEUR03EUR10YZ_A

如果eur在字符串中是两次,那我怎么能消除这个?很抱歉在我原来的帖子中没有包括这个,但我忘了这种情况是可能的,现在这是一个问题。

编辑:

在此示例中测试您的查询: http://www.sqlfiddle.com/#!3/21610/1

请注意最后它可以是1或2位数字和字母y或m的任意组合。

例如:ab_rtgtEUR03EUR2YZ_Aab_rtgtEUR03EUR2mZ_Aab_rtgtEUR03EUR20YZ_Aab_rtgtEUR03EUR20mZ_A

测试的一些值: ('ex_CHFCHF01CHF10YZ_A'), ('ab_rtgtEUR03EUR2YZ_A'), ('RON_asdRON2MZ_A'), ('tg_USDUSD04USD5YZ_A');

我对你的疑问的理解是,他们执行与此相似的事情(或至少他们应该)

ex_CHFCHF01CHF10YZ_A -> ex_CHFCHF01CHF10Y -> Y01FHC10FHCFHC -> Y01FHC -> CHF01Y -> CHF_01Y
RON_asdRON2MZ_A      ->  RON_asdRON2M     -> M2NORdsa_ron   -> M2NOR  -> RON2M  -> RON_2M

3 个答案:

答案 0 :(得分:3)

这适用于一位或两位数字:

stuff(case
        when name like '%[0-9][0-9]_z[_]a'
          then left(right(name, 9), 6)
        when name like '%[0-9]_z[_]a'
          then left(right(name, 8), 5)
      end, 4, 0, '_')

答案 1 :(得分:2)

您可以使用substringreversecharindex的组合。

SQL Fiddle

select substring(namenew,1,3) + '_' + substring(namenew, 4, len(namenew))
from (
select 
case when name like '%[0-9][0-9]_z[_]a' then 
reverse(substring(reverse(name), charindex('a_z',reverse(name)) + 3, 6)) 
     when name like '%[0-9]_z[_]a' then 
reverse(substring(reverse(name), charindex('a_z',reverse(name)) + 3, 5)) 
end as namenew
from myTable 
) t

答案 2 :(得分:1)

试试这样:

declare @tbl TABLE(name VARCHAR(100));
insert into @tbl VALUES
 ('asd_abceur1mz_a')
,('asd_fxasdrasdusd3mz_a')
,('asd_abceur10yz_a')
,('asd_fxasdrasdusd15yz_a')
,('ab_dertEUR03EUR10YZ_A');

WITH CutOfThreeAtTheEnd AS
(
    SELECT LEFT(name,LEN(name)-3) AS nameNew
    FROM @tbl
)
,Max6CharsFromEnd AS
(
    SELECT RIGHT(nameNew,6) AS nameNew
    FROM CutOfThreeAtTheEnd
)
SELECT nameNew  
      ,FirstNumber.Position
      ,Parts.*
      ,Parts.FrontPart + '_' + Parts.BackPart AS FinalString
FROM Max6CharsFromEnd 
CROSS APPLY
(
    SELECT MIN(x) 
    FROM
    (
              SELECT CHARINDEX('0',nameNew,1) AS x
        UNION SELECT CHARINDEX('1',nameNew,1)
        UNION SELECT CHARINDEX('2',nameNew,1)
        UNION SELECT CHARINDEX('3',nameNew,1)
        UNION SELECT CHARINDEX('4',nameNew,1)
        UNION SELECT CHARINDEX('5',nameNew,1)
        UNION SELECT CHARINDEX('6',nameNew,1)
        UNION SELECT CHARINDEX('7',nameNew,1)
        UNION SELECT CHARINDEX('8',nameNew,1)
        UNION SELECT CHARINDEX('9',nameNew,1)
    ) AS tbl
    WHERE x>0
) AS FirstNumber(Position)
CROSS APPLY(SELECT SUBSTRING(nameNew,FirstNumber.Position,1000) AS BackPart
                  ,SUBSTRING(nameNew,FirstNumber.Position-3,3) AS FrontPart) AS Parts

这是结果:

nameNew    Position BackPart    FrontPart   FinalString
ceur1m     5        1m          eur         eur_1m
dusd3m     5        3m          usd         usd_3m
eur10y     4        10y         eur         eur_10y
usd15y     4        15y         usd         usd_15y
EUR10Y     4        10Y         EUR         EUR_10Y
相关问题