Ich verwende SQL Server 2012
SELECT
0.15 * 30 / 360,
0.15 / 360 * 30
Ergebnisse:
0.012500,
0.012480
Dieser ist für mich noch verwirrender:
DECLARE @N INT = 360
DECLARE @I DECIMAL(38,26) = 0.15 * 30 / 360
DECLARE @C DECIMAL(38,26) = 1000000
SELECT @C * @I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 )
SELECT @C * (@I * POWER(1 + @I, @N) / ( POWER(1 + @I, @N) - 1 ) )
Die erste Auswahl gibt mir das richtige Ergebnis: 12644.44022 Die zweite Auswahl schneidet das Ergebnis ab: 12644.00000
sql-server
sql-server-2012
t-sql
decimal
cpacheco
quelle
quelle
Antworten:
Die Bestimmung der Genauigkeit und Skalierung, die sich aus Ausdrücken ergibt, ist ein Rattennest, und ich glaube, niemand versteht die genauen Regeln in jedem Szenario, insbesondere beim Mischen von Dezimal (oder Float!) Und Int. Siehe diese Antwort von gbn .
Sie können die Ausdrücke natürlich so anpassen, dass sie Ihnen das bieten, was Sie möchten, indem Sie viel ausführlichere explizite Konvertierungen vornehmen. Dies ist wahrscheinlich übertrieben, aber:
Keines der Ergebnisse wird aufgrund einer gebrochenen Gleitkomma-Mathematik oder einer völlig falschen Genauigkeit / Skalierung falsch gerundet.
quelle
Wie Aaron Bertrand erwähnte, sind Ausdrücke sehr schwierig vorherzusagen.
Wenn Sie es wagen, dorthin zu gehen, können Sie versuchen, mithilfe des folgenden Ausschnitts einen Einblick zu gewinnen:
Das ist das Ergebnis:
quelle
Ungeachtet der hervorragenden Antworten, die dieser Frage bereits hinzugefügt wurden, gibt es eine explizit definierte Rangfolge für die Konvertierung von Datentypen in SQL Server.
Wenn ein Operator zwei Ausdrücke unterschiedlicher Datentypen kombiniert, geben die Regeln für die Priorität des Datentyps an, dass der Datentyp mit der niedrigeren Priorität in den Datentyp mit der höheren Priorität konvertiert wird. Wenn die Konvertierung keine unterstützte implizite Konvertierung ist, wird ein Fehler zurückgegeben. Wenn beide Operandenausdrücke denselben Datentyp haben, hat das Ergebnis der Operation diesen Datentyp.
SQL Server verwendet die folgende Rangfolge für Datentypen:
Wenn Sie beispielsweise
SELECT 0.5 * 1
eine Dezimalstelle mit einem Int multiplizieren, erhalten Sie ein Ergebnis, das in einen Dezimalwert konvertiert wird, dadecimal
es eine höhere Priorität als derint
Datentyp hat.Weitere Informationen finden Sie unter http://msdn.microsoft.com/en-us/library/ms190309.aspx .
Trotzdem
SELECT @C * (@I * POWER(1 + @I, @N) / (POWER(1 + @I, @N) - 1 ));
sollte wahrscheinlich ein Dezimalwert zurückgegeben werden, da praktisch alle Eingaben dezimal sind. Interessanterweise können Sie ein korrektes Ergebnis erzwingen, indem Sie Folgendes ändernSELECT
:Dies gibt zurück:
Ich kann nicht erklären, wie das einen Unterschied macht, obwohl dies eindeutig der Fall ist . Ich vermute, dass der
1E0
(explizite Gleitkommawert) in derPOWER(
Funktion SQL Server dazu zwingt, eine andere Auswahl für die Ausgabetypen für diePOWER
Funktion zu treffen . Wenn meine Vermutung richtig ist, würde dies auf einen möglichen Fehler in derPOWER
Funktion hinweisen , da in der Dokumentation angegeben ist, dass die erste EingabePOWER()
ein Float oder eine Zahl ist, die implizit in einen Float konvertiert werden kann.quelle
Kennen Sie die
SELECT .. INTO
Syntax ? Dies ist ein nützlicher Trick, um Situationen wie diese zu dekonstruieren, da im laufenden Betrieb eine Tabelle mit genau den richtigen Datentypen für die angegebeneSELECT
Liste erstellt wird.Sie können Ihre Berechnung in ihre einzelnen Schritte aufteilen und dabei die Vorrangregeln von SQL Servern anwenden, um zu sehen, wie sich die Definition ändert. So würde Ihr erstes Beispiel aussehen:
Dies ist die Ausgabe:
quelle
(1+1)
und2
sind vom Typ,int
aber diese Frage hat ein Beispiel, bei dem sie am Ende ein anders typisiertes Ergebnis liefern.