从varchar列中提取数值以与数字列进行比较

时间:2015-03-19 10:57:00

标签: sql sql-server sql-server-2008

enter image description here

如何比较两列中给出的金额值,如附图所示? ' T',' M'和' B'第1列分别代表万亿,百万和十亿。到目前为止,我已经尝试了下面提到的代码,但这不是我需要的。

left(f.name, CHARINDEX('M',f.name))

See the attached image

注意:货币前缀可以是:$, GBP, GB, CAD等:

4 个答案:

答案 0 :(得分:0)

这将证明我上面的评论。它使用LEFT(), RIGHT(), CHARINDEX() and SUBSTRING()CASE的组合来确定乘数值。

declare @Text varchar(20) = '$30M Sales in Jan 2014'


SELECT @Text [OriginalText]
    --select only the letter
    ,Right(left(@Text, CHARINDEX(' ',@Text)-1),1) [Multiplier]
    --this trims the multiplier and the dollar sign
    ,SUBSTRING(left(@Text, CHARINDEX(' ',@Text)-1),2, len(left(@Text, CHARINDEX(' ',@Text)-1))-2) [ValueToMultiply]
    ,CASE Right(left(@Text, CHARINDEX(' ',@Text)-1),1)
        WHEN 'T' then 1000000000000
        WHEN 'B' then 1000000000
        WHEN 'M' then 1000000
    END 
    *  Convert(decimal(18,4),SUBSTRING(left(@Text, CHARINDEX(' ',@Text)-1),2, len(left(@Text, CHARINDEX(' ',@Text)-1))-2)) [FinalValue]

这导致:

OriginalText          | Multiplier  | ValueToMultiply   | FinalValue
$30M Sales in Jan 20  | M           | 30                | 30000000.0000

答案 1 :(得分:0)

试试这个:

DECLARE @t TABLE ( A NVARCHAR(MAX) )
INSERT  INTO @t
VALUES  ( '$55T sdlkjf' ),
        ( '$30M sdlkjf' ),
        ( '$0.30M sdlkjf' ),
        ( '$0.5B sdlkjf' )


SELECT  CAST(SUBSTRING(A, 1, CHARINDEX(' ', A) - 2) AS MONEY)
        * CASE SUBSTRING(A, CHARINDEX(' ', A) - 1, 1)
            WHEN 'T' THEN 1000000000000
            WHEN 'B' THEN 1000000000
            WHEN 'M' THEN 1000000
            ELSE 1
          END AS Result
FROM    @t

输出:

Result
55000000000000.0000
30000000.0000
300000.0000
500000000.0000

答案 2 :(得分:0)

您可以使用字符串操作来提取字符串的数字部分,并使用CASE语句将这些值相乘以生成可用于比较结果的数值。

执行转化的示例查询:

CREATE TABLE #temp (col1 VARCHAR(20), col2 DECIMAL (18, 2))

INSERT INTO #temp
        ( col1, col2 )
VALUES ('$55T Sales blah', 55000000000000),
       ('$30M Sales blah', 30000000),
       ('$0.3M Sales blah', 300000),
       ('$0.5B Sales blah', 500000000)

SELECT CASE SUBSTRING(col1, (CHARINDEX(' Sales', col1) - 1), 1) 
            WHEN 'T' 
            THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000000000
            WHEN 'B' 
            THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000000
            WHEN 'M' 
            THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000
        END AS NumericValue, 
        col2
FROM #temp

从这些数据中,您可以简单地比较两列,因此您可以将其包装在子查询中,如下所示:

CREATE TABLE #temp (col1 VARCHAR(20), col2 DECIMAL (18, 2))

INSERT INTO #temp
        ( col1, col2 )
VALUES ('$55T Sales blah', 55000000000000),
       ('$30M Sales blah', 30000000),
       ('$0.3M Sales blah', 300000),
       ('$0.5B Sales blah', 500000000)

SELECT t.NumericValue, 
       t.col2, 
       CASE WHEN t.NumericValue = t.col2 
            THEN 'Match' 
            ELSE 'No Match' 
        END AS Match 
FROM ( SELECT CASE SUBSTRING(col1, (CHARINDEX(' Sales', col1) - 1), 1) 
                    WHEN 'T' 
                    THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000000000
                    WHEN 'B' 
                    THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000000
                    WHEN 'M' 
                    THEN CONVERT(DECIMAL(18, 2), SUBSTRING(col1, 2, (CHARINDEX(' Sales', col1) - 3))) * 1000000
                END AS NumericValue, 
                col2
        FROM #temp) t

DROP TABLE #temp

这假设数字部分后面跟着“Sales”,并遵循您在示例数据中显示的格式。如果需要,您可以使用空格替换CHARINDEX中的“销售”。

<强>输出:

NumericValue        col2                Match
==============================================
55000000000000.00   55000000000000.00   Match
30000000.00         30000000.00         Match
300000.00           300000.00           Match
500000000.00        500000000.00        Match

更新了查询以考虑不同的前缀:

这使用PATINDEX('%[0-9]%', col1)来查找第一个数值的位置。

CREATE TABLE #temp
    (
      col1 VARCHAR(20) ,
      col2 DECIMAL(18, 2)
    )

INSERT  INTO #temp
        ( col1, col2 )
VALUES  ( 'GBP55T Sales blah', 55000000000000 ),
        ( '$30M Sales blah', 30000000 ),
        ( 'GB0.3M Sales blah', 300000 ),
        ( '$0.5B Sales blah', 500000000 )

SELECT  t.NumericValue ,
        t.col2 ,
        CASE WHEN t.NumericValue = t.col2 THEN 'Match'
             ELSE 'No Match'
        END AS Match
FROM    ( SELECT    CONVERT(DECIMAL(18, 2), SUBSTRING(col1,
                                                      PATINDEX('%[0-9]%', col1),
                                                      CHARINDEX(' ', col1)
                                                      - PATINDEX('%[0-9]%',
                                                              col1) - 1))
                    * CASE SUBSTRING(col1, ( CHARINDEX(' ', col1) - 1 ), 1)
                        WHEN 'T' THEN 1000000000000
                        WHEN 'B' THEN 1000000000
                        WHEN 'M' THEN 1000000
                      END AS NumericValue ,
                    col2
          FROM      #temp
        ) t

DROP TABLE #temp

感谢@Giorgi Nakeuri's answer更简洁的CASE声明。

答案 3 :(得分:-1)

TRY
SUBSTRING()REPLACE()

SUBSTRING ( expression ,start , length )

可以使用:

REPLACE ( string_expression , string_pattern , string_replacement )

e.g:

declare @val as varchar(200)='T31M4B5'

select 
CAST(
  (REPLACE(REPLACE(REPLACE(@Val,'M',''),'B',''),'T',''))
as int) as val

FIDDLE