[英]Optimization of a substring query with charindex to trim the left part of a string
[英]using charindex in a substring to trim a string
有一个列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_A
, ab_rtgtEUR03EUR2mZ_A
, ab_rtgtEUR03EUR20YZ_A
, ab_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
这适用于一个或两个数字:
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, '_')
您可以使用substring
, reverse
和charindex
的组合。
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
试试这样:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.