1

我在表 PriceTerm 中有一个包含各种字符串的 varchar 列。所以我想将其中一些复制到另一列。

所以源名称和格式是

[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 行,所以很多。

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

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

  1. 选择要转换的行。通过上面的 SQL 完成。
  2. 删除 % 所以字符串中只剩下数字。
  3. 将字符串转换为十进制并将其放在 PercentAddition 列中。

我的问题是如何实施第 2 步和第 3 步?

更新: 我已经尝试过这 2 个 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 转换为数字时出错。

但以下工作

SELECT CONVERT(decimal(28,10), LTRIM(RTRIM(REPLACE(REPLACE('5,8%', ',', '.'), '%', '')))) 从 PriceTerm WHERE AdditionalDescription like %[%]%'

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

从 PriceTerm WHERE(AdditionalDescription like '%[%]%')和 ISNUMERIC( LTRIM(RTRIM(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', '')))) = 0

PercentAddition
express + 30
Express Transport +30
tillägg till faktura 115423. express +30
+ 30    (1.30*42.4sek=55.12sek)
+ 30    (1.30*42.4sek=55.12sek)
7.5*
7.5*
7..5
7..5
7.5.
7.5.
1.5  (minimi 4.20 €)
335 * 25 = 418.75
335 * 25= 418.75
10.6 &
vastaanottajan rahdinmaksu +4
Expressfrakt!!+30

奇怪的是,这些都不包含 % 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

更新 PercentAddition 列

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 有 Try_Convert 在这种情况下非常有用。但我没有为 2008 R2 找到类似的替代方案。

4

3 回答 3

2

不要谈论这将是多么有效:

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

解释:

  1. 用空格替换 %
  2. 替换,.
  3. 删除任何前导或尾随空格。
  4. 转换为decimal(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]- 我们只对以数字开头的数据感兴趣。
  • %- 在数字之后可以包含任何字符。isnumeric我们使用inwhere子句处理非数字。
  • [,.]- 我们有数据有,.
  • %- 在[,.]它可能包含任何字符之后。isnumeric我们使用inwhere子句处理非数字。
  • [%0-9]- 我们希望数据以数字或%.

注意:'[0-9]%[,.]%[%0-9]'当您发现更多坏字符时,您将不得不进行修改。

参考:

  1. SQLFiddle 玩:http ://sqlfiddle.com/#!3/09a34/4
  2. LIKE- http://msdn.microsoft.com/en-us/library/ms179859(v=sql.90).aspx
于 2013-07-29T17:30:59.530 回答
1

事实证明,如果字符串是数字,最难的部分是验证。内置过程 IsNumeric 返回误报。即使结果为 1 CONVERT 也无法将字符串转换为十进制。救援来自谷歌和这个网站

我使用存储过程。

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
于 2013-07-30T10:09:20.123 回答
1

这不是最快的方法,但试试这个:

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

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

于 2013-07-29T17:32:26.277 回答