2009-07-09 9 views
1

Ich habe es mit einem Legacy-System zu tun, bei dem ich einige fehlerhafte Datensätze basierend auf einer Spalte mit dem Datentyp Float identifizieren muss.TSQL zum Identifizieren langer Float-Werte

Gute Aufzeichnungen haben einen Wert von ...

1 
2 
1.01 
2.01 

Bad Aufzeichnungen etwas sind wie ..

1.009999999999999 
2.003423785643000 
3.009999990463260 

ich eine Reihe von select-Anweisungen versucht habe, wo ich Dezimal konvertieren und Cast zu einem Varchar und verwenden Sie die LEN() -Funktion, aber dies scheint nicht zu funktionieren, wie die guten Datensätze, die 1,01 werden 1,0100000000000000

--Edit Ich bin ein wenig clos er jetzt wie ich entdeckt habe, was ich tun kann (Gewicht * 100) und all die guten Aufzeichnungen werden ganzzahlige Werte wie 101.201.265.301.500, etc ... und schlechte wie 2,00999999046326 werden 200,999999046326

+0

FYI: die 'sqlserver' -Tag wurde zu 'sqlserver' umbenannt. –

Antwort

1

Das auf meinem SQL arbeitet Server 2005 DB:

select len(cast(cast(1.01 as float) as varchar)) 

Ergebnis:

In der Tat, es selbst lässt mich die Besetzung explizite varchar überspringen, wenn ich will:

select len(cast(1.011 as float)) 

Ergebnis:


Update: Zunächst einmal habe ich noch die Besetzung zu varchar benötigt. Anders zu denken war falsch. Das heißt, ich hatte das alles mit Strings arbeiten und war dabei, wie zu posten. Dann habe ich dein Update zum Multiplizieren mit 100 und merkte, dass das der richtige Weg war. Also hier ist mein Code zum Testen beider Möglichkeiten:

declare @test table (c float) 
insert into @test 
    select * from 
     (select 14.0100002288818 as c union 
      select 1.01 union 
      select 2.00999999046326 union 
      select 14.01 
     ) t 

select c, 
    case when c = cast(cast(c as varchar) as float) AND LEN(cast(c as varchar))<=5 then 1 else 0 end, 
    case when c * 100 = floor(c * 100) then 1 else 0 end 
from @test 
+0

Wenn ich das zu meiner WHERE-Klausel hinzufüge, wird es zurückgegeben (0 Zeile (n) betroffen). UND LEN (CAST (Gewicht als FLOAT))> 5 – DBAndrew

+0

Ist 'Gewicht' nicht schon ein Schwimmer? Haben Sie versucht, nur die Gewichtskolonne, len (Gewicht) und Reihenfolge von len (Gewicht) auszuwählen? –

+0

Dies gilt nicht als gute Bilanz arbeiten können LEN 14.01 und gibt sein() von 5 und eine schlechte 14,0100002288818 gibt auch eine LEN() von 5 ... SELECT \t ID, \t Gewicht, \t LEN (Gewicht) vON \t Produkte MIT (NOLOCK) ORDER BY \t LEN (Gewicht) – DBAndrew

1

etwas so, vielleicht? (Stellen Sie die Präzision/Skala in der where-Klausel, natürlich)

select val from mytable WHERE CONVERT(decimal(5,2), val) <> val 
+0

Dies gibt immer noch viele Ergebnisse zurück, die 1.01, 2.01, 3.01 usw. sind. Es zeigt mehr von den schlechten wie 2.00999999046326 – DBAndrew

0

Sie so etwas tun könnte:

SELECT * 
FROM YourTable 
WHERE CAST(YourFloatField AS DECIMAL(15,2)) <> YourFloatField 

Ich gehe davon aus, dass alles, was „schlecht“ hat mehr als 2 Dezimalstellen gegeben.

+0

Ich bekomme immer noch viele 1,01,2,01,3,01 etc .. wenn ich füge folgendes zu meiner WHERE-Klausel hinzu ... UND CAST (GEWICHT ALS DEZIMAL (15,2)) <> GEWICHT – DBAndrew

0

Dies wird wirklich zu einer Nervensäge werden, da Floats ein ungenauer Datentyp sind und Sie beim Konvertieren implizite Konvertierungen erhalten.

es hängt auch davon, wo Sie so etwas wie die folgenden

select convert(float,1.33) 

in Query Analyzer die Ausgabe 1,3300000000000001 in SSMS ist der Ausgang 1 ist.33

, wenn Sie konvertieren Sie eine Dezimalzahl, wenn Sie

select convert(decimal(10,6),convert(float,1.33)) 

SieFormal diese 1,330000 erhalten angeben müssen Umfang und Präzision

so tun, weil Sie eine Skala von 6

angegeben Sie tun konnten, etwas wie dies, wo nach der Konvertierung in Dezimal Sie die hinteren 0s

select replace(rtrim(replace(convert(varchar(30), 
    (convert(decimal(10,6),convert(float,1.33)))),'0',' ')),' ','0') 
fallen lassen 0

für einen Wert von 3,00999999046326 benötigen Sie eine Skala von mindestens 14

select replace(rtrim(replace(convert(varchar(30), 
    (convert(decimal(30,14),convert(float,3.00999999046326)))),'0',' ')),' ','0') 
+2

Deshalb habe ich Float aus meinen Schemas verbannt ... – devstuff

+0

Vielleicht hast du mein Problem nicht verstanden. Wenn ich dies auf den ausgewählten Teil meiner SQL-Anweisung anwende, macht es nur einen 3.00999999046326 zu 3.01, was mir nicht wirklich hilft. Vielleicht vermisse ich deine Antwort ... – DBAndrew

+1

Ich stimme zu, ich weigere mich zu erlauben, Floats und Reals in Vorwärtsgehen. – DBAndrew

1

Haben Sie sich Gedanken über CLR-Integration verwenden und .net mit der Validierung behandeln Link siehe Basics of Using a .NET Assembly in MS SQL - User Functions

grundsätzlich Sie verwenden. Net-Methoden als eine benutzerdefinierte Funktion, um die Validierung durchzuführen; .NET ist besser im Umgang mit Zahlen. diese

0

Run:

DECLARE @d FLOAT; 
SET @d = 1.23; 
SELECT ABS(CAST(@d AS DECIMAL(10,2)) - CAST(@d AS DECIMAL(15,8))); 
SET @d = 1.230000098; 
SELECT ABS(CAST(@d AS DECIMAL(10,2)) - CAST(@d AS DECIMAL(15,8))); 

bestimmte Schwelle verwenden wie:

ABS(CAST(@d AS DECIMAL(10,2)) - CAST(@d AS DECIMAL(15,8)))<0.00001 
Verwandte Themen