2010-03-11 4 views
1
DECLARE @table table(XYZ VARCHAR(8) , id int) 

INSERT INTO @table 
SELECT '4000', 1 
UNION ALL 
SELECT '3.123', 2 
UNION ALL 
SELECT '7.0', 3 
UNION ALL 
SELECT '80000', 4 
UNION ALL 
SELECT NULL, 5 

Requête:SQL Server - CAST et divisez

SELECT CASE 
     WHEN PATINDEX('^[0-9]{1,5}[\.][0-9]{1,3}$', XYZ) = 0 THEN XYZ 
     WHEN PATINDEX('^[0-9]{1,8}$',XYZ) = 0 THEN CAST(XYZ AS decimal(18,3))/1000 
     ELSE NULL 
     END 
    FROM @table 

Cette partie - CAST(XYZ AS decimal(18,3))/1000 ne divise pas la valeur.

Il me donne plus de nombre de zéros après décimal au lieu de le diviser. (J'ai même inclus cela entre parenthèses et essayé mais le même résultat).

Ex:2000/1000 = 2000.000000 

Est-ce que je fais quelque chose de mal ici? Les paramètres d'expression de patindex sont-ils corrects?

Expected result: 
4.000 
3.123 
7.000 
80.000 

Faites-moi savoir si PATINDEX n'est pas la bonne méthode à utiliser? Je suis en train de vérifier si elle est déjà décimal avec 3 points décimaux autre que je veux diviser par 1000.

+0

Salut, j'ai quelque chose à travailler presque qui évite PATINDEX. Quelles sont les règles pour plonger de 1000? Si XYZ inclut un point décimal, laissez tel quel, si ce n'est pas 1000? – CResults

+1

PATINDEX (Transact-SQL) http://msdn.microsoft.com/en-us/library/ms188395.aspx Retourne la position de départ de la première occurrence d'un motif dans une expression spécifiée, ou zéro si le motif n'est pas trouvé , sur tous les types de données de texte et de caractères valides. –

+0

@CResults - Il devrait toujours être en décimal mais parfois nous obtenons de mauvaises données 4.000 comme 4000 ou 2.310 comme 2310. Donc ce que j'essaie de faire est de vérifier s'il n'est pas dans xx.xxx le convertir en format décimal. Oui si le point d'incultion le laisse –

Répondre

1

Essayez ceci ..

DECLARE @table table(XYZ VARCHAR(8) , id int) 

INSERT INTO @table 
SELECT '4000', 1 
UNION ALL 
SELECT '3.123', 2 
UNION ALL 
SELECT '7.0', 3 
UNION ALL 
SELECT '80000', 4 
UNION ALL 
SELECT NULL, 5 
UNION ALL 
SELECT 'WTF',6 

SELECT CASE 
    WHEN ISNUMERIC(XYZ) = 0 THEN NULL 
    WHEN CHARINDEX('.',XYZ,0) < LEN(XYZ)-2 AND CHARINDEX('.',XYZ,0) > 0 THEN XYZ 
    WHEN ISNUMERIC(XYZ) >0 then convert(decimal(18,3),xyz)/1000.000 
    ELSE NULL 
END 
    FROM @table 

Sortie

4.00000000000 
3.12300000000 
0.00700000000 
80.00000000000 
NULL 
NULL 

Edit - pour maintenir à 3 la (8,3) décimales en sortie faire

SELECT convert(decimal(8,3),CASE 
    WHEN ISNUMERIC(XYZ) = 0 THEN NULL 
    WHEN CHARINDEX('.',XYZ,0) < LEN(XYZ)-2 AND CHARINDEX('.',XYZ,0) > 0 THEN XYZ 
    WHEN ISNUMERIC(XYZ) >0 then convert(decimal(18,3),xyz)/1000.000 
    ELSE NULL 
END) 
    FROM @table 

note définit ce, au total précision 8 chiffres, 3 après le point.

Vous voudrez peut-être reconvertir en varchar (8) trop

+0

parfait merci c'est ce que je cherchais, mais pourquoi est-ce pad 8 + 8 à la fin? –

+0

voir mon édition. J'ai gardé la précision à 8 pour convenir à votre varchar d'origine – CResults

+0

oui merci, je suis confus au sujet de ce qui l'amène à combler autant de zéros. –

0

Dividing par 1000 vous donnera plus de zéros après la virgule décimale

5.3/1000 = .0053 
+0

non, le PATINDEX qu'il utilise empêche les valeurs avec un point décimal d'être divisé par 1000 – CResults

+0

lol ma question est confuse corrigera il, 2000/1000 = 2000.000000 est ce que je reçois –

1

essayer, convertir l'ensemble du dossier en décimal (18,3):

DECLARE @table table(XYZ VARCHAR(8) , id int) 

INSERT INTO @table 
SELECT '4000', 1 
UNION ALL 
SELECT '3.123', 2 
UNION ALL 
SELECT '7.0', 3 
UNION ALL 
SELECT '80000', 4 
UNION ALL 
SELECT NULL, 5 


SELECT CONVERT(decimal(18,3),CASE --nothing changes within the CASE 
           WHEN PATINDEX('^[0-9]{1,5}[\.][0-9]{1,3}$', XYZ) = 0 THEN XYZ 
           WHEN PATINDEX('^[0-9]{1,8}$',XYZ) = 0 THEN CAST(XYZ AS decimal(18,3))/1000 
           ELSE NULL 
          END 
      ) 
FROM @table 

SORTIE:

--------------------------------------- 
4000.000 
3.123 
7.000 
80000.000 
NULL 

(5 row(s) affected) 
+0

ne fonctionne pas. Je suppose que PATINDEX ne fait pas ce que je m'attendais à faire –

+0

comment «ne fonctionne pas», fonctionne pour toutes les données d'échantillon donné? –

+0

si nous divisons par 1000, 4000.000 = 4.000? –

0
select xyz, ((case when charindex('.', xyz) > 0 then cast(xyz AS decimal(18,3))*1000 
        else cast(xyz AS decimal(18,3)) end))/1000 
from #table 
+0

ne fonctionne pas. elle renvoie les mêmes valeurs –

+0

fixe, essayez à nouveau – HLGEM

+0

vous êtes à proximité, mais on n'a pas besoin que * 1000 supplémentaire là :) –