如何使用SUBSTRING使用2个不同的分隔符提取数据?

时间:2017-05-30 16:35:28

标签: sql sql-server-2008 tsql

处理具有字符串列的表。以下是字符串外观的一些示例:

 Fee Prorated 68%  -  $1.00  x 76
 Fee - Prorated 50% ($1.10 x 292)
 Fee - Prorated 50% ($1.00 x 242)
 Fee - Prorated 13% ($1.00 x 39)
 Prorated  Fee 45.16%  $1.00 x 256
 Fee - Prorated 26% ($1.00 x 56)
 Fee- Prorated 51.6%  $1.00 x 66
 Fee - Prorated 94% ($1.15 x 48)
 Fee - Prorated 52% ($1.10 x 120)
 Fee - Prorated 10% ($1.25 x 304)
 Fee - Prorated 10% ($1.25 x 304)
 Fees - prorated 46.67% ($1.50 x 230)
 Fees - prorated 23% ($1.25 x 989)
 Fees - prorated 87% ($1.25 x 348)
 Fees - prorated 48% ($1.25 x 210)
 Fees ($1.50 x 64) Prorated 30%
 Fees - prorated 30% ($1.50 x 51)
 Fees ($1.25 x 341) - Prorated 71%
 Fees - Prorated 58% ($1.50 x 196)
 Fees - Prorated 10% ($1.25 x 224)
 Fees - Prorated 61%($1.50 x 50)

我需要获得一个只是百分比的子字符串,这样我就可以将其转换为小数,然后乘以该数量。

我不知道如何做到这一点,除了尝试使用%作为分隔并抓住它左边的所有内容,直到它到达空格字符 - 问题是我不知道怎么做< / p>

3 个答案:

答案 0 :(得分:3)

使用charindex()reverse()left()来确定substring()的参数:

select 
    col
  , substring(
      col
    , charindex('%',col) - (charindex(' ',reverse(left(col,charindex('%',col)))+' ')-2)
    ,(charindex(' ',reverse(left(col,charindex('%',col)))+' ')-2)
    ) as Prorated
from t
where charindex('%',col)>0

rextester演示:http://rextester.com/GKVB60235

返回:

+--------------------------------------+----------+
|                 col                  | Prorated |
+--------------------------------------+----------+
| Fee Prorated 68%  -  $1.00  x 76     | 68       |
| Fee - Prorated 50% ($1.10 x 292)     | 50       |
| Fee - Prorated 50% ($1.00 x 242)     | 50       |
| Fee - Prorated 13% ($1.00 x 39)      | 13       |
| Prorated  Fee 45.16%  $1.00 x 256    | 45.16    |
| Fee - Prorated 26% ($1.00 x 56)      | 26       |
| Fee- Prorated 51.6%  $1.00 x 66      | 51.6     |
| Fee - Prorated 94% ($1.15 x 48)      | 94       |
| Fee - Prorated 52% ($1.10 x 120)     | 52       |
| Fee - Prorated 10% ($1.25 x 304)     | 10       |
| Fee - Prorated 10% ($1.25 x 304)     | 10       |
| Fees - prorated 46.67% ($1.50 x 230) | 46.67    |
| Fees - prorated 23% ($1.25 x 989)    | 23       |
| Fees - prorated 87% ($1.25 x 348)    | 87       |
| Fees - prorated 48% ($1.25 x 210)    | 48       |
| Fees ($1.50 x 64) Prorated 30%       | 30       |
| Fees - prorated 30% ($1.50 x 51)     | 30       |
| Fees ($1.25 x 341) - Prorated 71%    | 71       |
| Fees - Prorated 58% ($1.50 x 196)    | 58       |
| Fees - Prorated 10% ($1.25 x 224)    | 10       |
| Fees - Prorated 61%($1.50 x 50)      | 61       |
+--------------------------------------+----------+

答案 1 :(得分:0)

从字符串之间获取数据并从中获取处理数据风险较大,从长远来看并不是有益的。所以我建议你找一下如何在列中加载%值,看看你是否可以在表格旁边加载一个单独的列。

如果不可能,并且如果字符串模式没有修复,那么您可以将charindexsubstringreverse组合使用。

我建议您按照评论中的提法检查regex方法,因为我担心这么多字符串函数可能会降低查询速度。因此,比较两种方法,并采用更快的方法。

Rextester Demo

 SELECT 
 reverse
    (substring
        (reverse
            (substring
                (col,1,charindex('%',col,1))
            ),2,charindex(' ',reverse
                                (substring(col,1,charindex('%',col,1))
                                ),1
                         )-2
        )
    ) as percentage
FROM
  (SELECT 'Fee Prorated 68%  -  $1.00  x 76' AS col
   UNION ALL SELECT 'Fee - Prorated 50.0987% ($1.10 x 292)') t

输出

percentage
----------
68
50.0987

答案 2 :(得分:0)

另一种选择是使用Parse / Split功能。

这里我们使用[SPACE]作为分隔符,但稍加扭曲以确保捕获。在我们将字符串传递给解析器之前,我们将[PERCENT]替换为[PERCENT] || [SPACE]

示例

Select A.*
      ,Pcnt = replace(B.RetVal,'||','')
 From  YourTable A
 Cross Apply [dbo].[udf-Str-Parse-8K](replace(A.SomeCol,'%','%|| '),' ') B
 Where RetVal Like '%||'

<强>返回

SomeCol                              Pcnt
Fee Prorated 68% - $1.00 x 76       68%
Fee - Prorated 50% ($1.10 x 292)    50%
Fee - Prorated 50% ($1.00 x 242)    50%
Fee - Prorated 13% ($1.00 x 39)     13%
Prorated Fee 45.16% $1.00 x 256     45.16%
Fee - Prorated 26% ($1.00 x 56)     26%
Fee- Prorated 51.6% $1.00 x 66      51.6%
Fee - Prorated 94% ($1.15 x 48)     94%
Fee - Prorated 52% ($1.10 x 120)    52%
Fee - Prorated 10% ($1.25 x 304)    10%
Fee - Prorated 10% ($1.25 x 304)    10%
Fees - prorated 46.67% ($1.50 x 230)46.67%
Fees - prorated 23% ($1.25 x 989)   23%
Fees - prorated 87% ($1.25 x 348)   87%
Fees - prorated 48% ($1.25 x 210)   48%
Fees ($1.50 x 64) Prorated 30%      30%
Fees - prorated 30% ($1.50 x 51)    30%
Fees ($1.25 x 341) - Prorated 71%   71%
Fees - Prorated 58% ($1.50 x 196)   58%
Fees - Prorated 10% ($1.25 x 224)   10%
Fees - Prorated 61%($1.50 x 50)     61%

UDF if Intersted

CREATE FUNCTION [dbo].[udf-Str-Parse-8K] (@String varchar(max),@Delimiter varchar(25))
Returns Table 
As
Return (  
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)

    Select RetSeq = Row_Number() over (Order By A.N)
          ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
    From   cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')