Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将SQL子字符串转换为十进制?_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

如何将SQL子字符串转换为十进制?

如何将SQL子字符串转换为十进制?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一个varchar列,表PriceTerm中有各种字符串。所以我想把其中一些复制到另一个专栏 因此,源名称和格式是 [AdditionalDescription] [varchar](255) NOT NULL 和目的地 [PercentAddition] [decimal](28, 10) NOT NULL 我只想强制转换那些包含由SQL拾取的% select AdditionalDescription from PriceTerm where AdditionalDescriptio

我有一个varchar列,表PriceTerm中有各种字符串。所以我想把其中一些复制到另一个专栏

因此,源名称和格式是

[AdditionalDescription] [varchar](255) NOT NULL
和目的地

[PercentAddition] [decimal](28, 10) NOT NULL
我只想强制转换那些包含由SQL拾取的%

select AdditionalDescription from PriceTerm where AdditionalDescription like '%[%]%'
输出是这样的

AdditionalDescription
7,5 %
7,5%
7,5%
6 %
7,5%
6 %
3 %
....
返回1696475行,因此数量很多

显然,我必须先删除%符号,然后才能将其转换为十进制值

所以我认为这是几个子步骤

  • 选择要转换的行。由上面的SQL完成
  • 删除%以便字符串中只剩下一个数字
  • 将字符串转换为十进制,并将其放入列PercentAddition中
  • 我的问题是如何实施步骤2和步骤3

    更新: 我试过这两个SQL

    SELECT 
    CONVERT(decimal(28,10), LTRIM(RTRIM(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', ''))))
    FROM PriceTerm
    WHERE AdditionalDescription like '%[%]%'
    
    SELECT 
    CAST(LTRIM(RTrim(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', ''))) AS Decimal(28,10))
    FROM PriceTerm
    WHERE AdditionalDescription like '%[%]%'
    
    两者都返回了相同的错误

    将数据类型varchar转换为数字时出错

    但是下面的工作

    挑选 转换(十进制(28,10)、LTRIM(RTRIM(替换(替换('5,8%,',',','),'%,''),'%,'')) 从价格术语 其中,类似“%[%]”的附加说明

    我试着列出那些满足条件但转换失败的

    挑选 LTRIM(RTRIM(替换(替换([附加说明],,,,,,,,,,,),,,,,))作为百分比添加 从价格术语 其中(类似“%[%]%”的附加描述)和ISNUMERIC(LTRIM(RTRIM(替换(替换([AdditionalDescription],“,”,“,”),“%,”))=0

    奇怪,这些都不包含%char

    更新2: 我尝试过滤掉无法使用此SQL转换的数据

    SELECT AdditionalDescription
    FROM PriceTerm 
    WHERE Created BETWEEN '2004' AND '2005' AND
    AdditionalDescription like '%[%]%' AND
    PercentAddition = 0 AND 
    ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 0
    
    输出:

    AdditionalDescription
    
    Snabbleverans + 30 %
    Snabbleverans + 30 %
    455 € + 4%
    1,5 % (minimi 4,20 €)
    1,5 % (minimi 4,20 €)
    bränsle 7,5% ingår.
    
    因此,这些字符串包含%,但无法将其转换为小数。我想跳过那些

    计算有效数字

    SELECT Count(*)
    FROM PriceTerm 
    WHERE Created BETWEEN '2004' AND '2005' AND
    AdditionalDescription like '%[%]%' AND
    PercentAddition = 0 AND 
    ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
    
    80051

    更新百分比添加列

    UPDATE PriceTerm 
    SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'))))
    WHERE Created BETWEEN '2004' AND '2005' AND
    AdditionalDescription LIKE '%[%]%' AND
    PercentAddition = 0
    AND ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
    
    结果

    将数据类型varchar转换为数字时出错

    有人知道原因吗

    更新3:

    例如,上面所有无法解析的奇怪行都将被跳过

    + 30    (1.30*42.4sek=55.12sek)
    7.5*
    7.5*
    7..5
    
    以上全部转换为0。只有那些将转换为十进制:

    7,5%  -> 7.5
    7,7 % -> 7.7
    2.5   -> 2.5
    
    我还试图弄清楚SQL CASE WHEN是如何工作的。有什么有用的吗? 我试过这个:

    UPDATE PriceTerm 
    SET PercentAddition = 
      CASE
        WHEN ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1 THEN      
          CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'))))
        ELSE 
          0.0
        END 
    WHERE Created BETWEEN '2004' AND '2005' AND
    AdditionalDescription LIKE '%[%]%' AND
    PercentAddition = 0
    AND ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
    
    将数据类型varchar转换为数字时输出仍然错误。 我甚至考虑过一个存储过程,但我以前从未使用过。
    SQL Server 2012已尝试转换,这在本例中非常有用。但我没有找到类似的2008 R2替代方案。

    不知道这将有多高效:

    Select convert(decimal(28,10), rtrim(ltrim(replace(REPLACE(AdditionalDescription,'%',''), ',','.')))) As AdditionalDescription
    from PriceTerm 
    where AdditionalDescription like '%[%]%'
    
    说明:

  • 用空格替换以删除%
  • 替换为
  • 删除任何前导或尾随空格
  • 转换为十进制(28,10)
  • 更新: 根据OP提供的其他信息

    Select 
    convert(decimal(28,10),replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%','')) AS PercentAddition
    from test 
    where replace(rtrim(ltrim(AdditionalDescription)), ' ','')
    like '[0-9]%[,.]%[%0-9]'
    and 
    isnumeric(replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%',''))=1
    
    解释
    '[0-9]%[,.]%[%0-9]'

    • [0-9]
      -我们只对数据以数字开头的情况感兴趣
    • %
      -数字后可能包含任何字符。我们在
      where
      子句中处理带有
      isnumeric
      的非数字
    • [,.]
      -我们有
      的数据
    • %
      -在
      [,.]
      之后,它可以包含任何字符。我们在
      where
      子句中处理带有
      isnumeric
      的非数字
    • [%0-9]
      -我们希望数据以数字或
      %
      结尾
    注意:当您发现更多错误字符时,您必须修改
    '[0-9]%[,.]%[%0-9]'

    参考文献:

  • 要使用的SQLFiddle:
  • -

  • 不要担心这会有多高效:

    Select convert(decimal(28,10), rtrim(ltrim(replace(REPLACE(AdditionalDescription,'%',''), ',','.')))) As AdditionalDescription
    from PriceTerm 
    where AdditionalDescription like '%[%]%'
    
    说明:

  • 用空格替换以删除%
  • 替换为
  • 删除任何前导或尾随空格
  • 转换为十进制(28,10)
  • 更新: 根据OP提供的其他信息

    Select 
    convert(decimal(28,10),replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%','')) AS PercentAddition
    from test 
    where replace(rtrim(ltrim(AdditionalDescription)), ' ','')
    like '[0-9]%[,.]%[%0-9]'
    and 
    isnumeric(replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%',''))=1
    
    解释
    '[0-9]%[,.]%[%0-9]'

    • [0-9]
      -我们只对数据以数字开头的情况感兴趣
    • %
      -数字后可能包含任何字符。我们在
      where
      子句中处理带有
      isnumeric
      的非数字
    • [,.]
      -我们有
      的数据
    • %
      -在
      [,.]
      之后,它可以包含任何字符。我们在
      where
      子句中处理带有
      isnumeric
      的非数字
    • [%0-9]
      -我们希望数据以数字或
      %
      结尾
    注意:当您发现更多错误字符时,您必须修改
    '[0-9]%[,.]%[%0-9]'

    参考文献:

  • 要使用的SQLFiddle:
  • -

  • 这不是最快的方法,但请尝试以下方法:

    SELECT CONVERT(DECIMAL(5, 2), REPLACE(REPLACE(AdditionalDescription, '%', ''), ',', '.')) AS DecimalValue
    FROM   PriceTerm
    WHERE  AdditionalDescription LIKE '%[%]%'
    

    这将用空字符串替换%,用点替换逗号,因此7,5%看起来像7.5,然后转换为十进制。

    这不是最快的方法,但请尝试以下方法:

    SELECT CONVERT(DECIMAL(5, 2), REPLACE(REPLACE(AdditionalDescription, '%', ''), ',', '.')) AS DecimalValue
    FROM   PriceTerm
    WHERE  AdditionalDescription LIKE '%[%]%'
    

    这将用空字符串替换%,用点替换逗号,因此7,5%看起来像7.5,然后转换为十进制。

    事实证明,最难的部分是验证字符串是否为数字。内置过程IsNumeric返回假阳性。即使结果为1,转换也无法将字符串转换为十进制。拯救行动是伴随着谷歌而来的

    我使用存储过程

    CREATE FUNCTION dbo.isReallyNumeric  
    (  
        @num VARCHAR(64)  
    )  
    RETURNS BIT  
    BEGIN  
        IF LEFT(@num, 1) = '-'  
            SET @num = SUBSTRING(@num, 2, LEN(@num))  
    
        DECLARE @pos TINYINT  
    
        SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))  
    
        RETURN CASE  
        WHEN PATINDEX('%[^0-9.-]%', @num) = 0  
            AND @num NOT IN ('.', '-', '+', '^') 
            AND LEN(@num)>0  
            AND @num NOT LIKE '%-%' 
            AND  
            (  
                ((@pos = LEN(@num)+1)  
                OR @pos = CHARINDEX('.', @num))  
            )  
        THEN  
            1  
        ELSE  
        0  
        END  
    END  
    GO 
    
    然后像这样使用它:

    UPDATE PriceTerm 
    SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) 
    WHERE AdditionalDescription LIKE '%[%]%' AND
    dbo.isreallynumeric(RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) = 1 AND
    PercentAddition = 0
    

    事实证明,最难的部分是验证字符串是否为数字。内置过程IsNumeric返回假阳性。即使结果为1,转换也无法将字符串转换为十进制。拯救行动是伴随着谷歌而来的

    我使用存储过程

    CREATE FUNCTION dbo.isReallyNumeric  
    (  
        @num VARCHAR(64)  
    )  
    RETURNS BIT  
    BEGIN  
        IF LEFT(@num, 1) = '-'  
            SET @num = SUBSTRING(@num, 2, LEN(@num))  
    
        DECLARE @pos TINYINT  
    
        SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))  
    
        RETURN CASE  
        WHEN PATINDEX('%[^0-9.-]%', @num) = 0  
            AND @num NOT IN ('.', '-', '+', '^') 
            AND LEN(@num)>0  
            AND @num NOT LIKE '%-%' 
            AND  
            (  
                ((@pos = LEN(@num)+1)  
                OR @pos = CHARINDEX('.', @num))  
            )  
        THEN  
            1  
        ELSE  
        0  
        END  
    END  
    GO 
    
    然后像这样使用它:

    UPDATE PriceTerm 
    SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) 
    WHERE AdditionalDescription LIKE '%[%]%' AND
    dbo.isreallynumeric(RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) = 1 AND
    PercentAddition = 0
    

    看起来你没有干净的数据。列中只填充了各种非数字字符。也许你必须清理数据。是的,我同意。但是我怎么能做到呢?我必须过滤