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行を返すので、たくさんあります。

明らかに、10 進数値にキャストする前に % 記号を削除する必要があります。

だから私はそれがいくつかのサブステップだと思います。

  1. 変換する行を選択します。上記の SQL によって行われます。
  2. % を削除して、文字列に数字だけを残します。
  3. 文字列を 10 進数に変換し、列 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%', ',', '.'), '%', '')))) FROM PriceTerm WHERE AdditionalDescription like ' %[%]%'

条件を満たし、変換に失敗するものをリストしようとします。

SELECT LTRIM(RTRIM(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', ''))) as PercentAddition FROM PriceTerm WHERE (AdditionalDescription like '%[%]%') AND ISNUMERIC( LTRIM(RTRIM(REPLACE(REPLACE([追加説明], ',', '.'), '%', '')))) = 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.

これらの文字列には % が含まれていますが、10 進数に変換することはできません。それらをスキップしたい。

有効数のカウント

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 に変換されます。これらのみが 10 進数に変換されます。

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

1

文字列が数値である場合、最も難しい部分は検証であることが判明しました。組み込みプロシージャ IsNumeric が誤検知を返しました。結果が 1 だったとしても、CONVERT は文字列を Decimal にキャストできませんでした。救助はGoogleとこのサイトで来ました

ストアドプロシージャを使用しています。

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 のように見え、10 進数に変換されます。

于 2013-07-29T17:32:26.277 に答える