Frage

Ich versuche, die Geldsummen in einigen schlecht formated XML-Spalten gespeichert zu extrahieren (es gibt kein Schema für die XML-Spalte definiert, die ich denke, einen Teil des Problems ist). Ich erhalte einen Konvertierungsfehler, wenn ich einen Knoten mit 0 als Wert begegnen.

Beispiel:

select xml.value('sum(/List/value)', 'numeric') sum
from (select cast('<List><value>1</value><value>2</value></List>' as xml) xml) a

gibt die Summe 3 während:

select xml.value('sum(/List/value)', 'numeric') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a

erhöht die Fehlermeldung: "Fehlerdatentyp nvarchar in numerischer Umwandlung"

Jede Idee, wie kann ich meine Abfrage return 0, wenn zusammenfassend eine Liste von nullwertigen Knoten?

machen
War es hilfreich?

Lösung

Ihr Kommentar schlägt vor, eine Antwort auf Ihr Problem.

Statt auf numerische umzuwandeln, konvertieren zu schweben. Wissenschaftliche Notation konvertiert zu schweben.

Andere Tipps

Sie können auch verwendet werden und if-Anweisung wie folgt aus:

@x.value('if (sum(/List/value) = 0) then 0 else sum(/List/value)', 'numeric')

ich auf dieser Frage gestolpert, und letztlich eine Antwort, während bei einem ähnlichen Problem mit ganzen Zahlen suchen. Trotz der Verzögerung seit der letzten Antwort, ich hinzufüge, hier im Fall hilft es sonst jemanden in der Zukunft.

Sie zuerst Ihre grundlegende Antwort:

select xml.value('xs:decimal(sum(/List/value))', 'numeric') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a

In XQuery Sie den Wert auf einen Standard-XML-Schema-Typen umgewandelt, die dann korrekt von SQL Server behandelt werden.

Bitte beachten Sie: die Standardeinstellung „numerisch“ in SQL Server hat keine Dezimalstellen (Skala von „0“)! Sie haben wahrscheinlich gedacht, etwas mehr wie zu tun:

select xml.value('xs:decimal(sum(/List/value))', 'numeric(20,5))') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a

(Sie können nicht SQL Server erhalten die Genauigkeit oder Skalierung von dem Wert aus dem XML zurück zu schließen, müssen Sie es explizit angeben)

Schließlich ist die eigentliche Frage, die ich persönlich Adresse brauchte, war fast genau die gleiche, außer mich mit ganzen Zahlen zu tun habe, die auch mit der XML-Darstellung von „0“ double Werten kämpfen:

select xml.value('xs:int(sum(/List/value))', 'int') sum
from (select cast('<List><value>0</value><value>0</value></List>' as xml) xml) a

UPDATE: Das Problem mit dem Dezimalsystem-Handling-Lösung, die ich oben geschrieben (Umwandlung in XQuery in Dezimalzahlen vor SQL den Wert Parsen wird) ist, dass die Aggregation wirklich geschieht mit dem (angenommener / gefolgerten) Gleitkomma- (Doppel) Datentyp. Wenn die Werte, die Sie in Ihrer XML gespeichert haben ein hohes Maß an Präzision erfordern, kann dies tatsächlich die falsche Sache zu tun - die Floating-Point-Aggregation tatsächlich zu einem Verlust von Daten führen kann. Zum Beispiel hier verlieren wir die letzte Ziffer der Zahl sind wir Summieren:

select xml.value('xs:decimal(sum(/List/value))', 'numeric(28, 0)') sum
from (select cast('<List>
        <value>1000000000000000000000000001</value>
        <value>1000000000000000000000000001</value>
    </List>' as xml) xml) a

(kommt auf "2000000000000000000000000000", was falsch ist)

Dieses Problem gilt auch für andere Ansätze hier angeboten, wie zum Beispiel den Wert explizit als „float“ in T-SQL zu lesen.

Um dies zu vermeiden, hier ist eine letzte Option eines XQuery FLWOR Ausdruck mit dem Datentyp auf vor die Aggregation Betrieb. In diesem Fall erfolgt die Aggregation richtig, und wir haben den richtigen summierte Wert (während auch Werte „0“ wenn / Handhabung, wenn sie auftreten):

select xml.value('sum(for $r in /List/value return xs:decimal($r))', 'numeric(28, 0)') sum
from (select cast('<List>
        <value>1000000000000000000000000001</value>
        <value>1000000000000000000000000001</value>
    </List>' as xml) xml) a

(kommt auf "2000000000000000000000000002", der richtige Wert)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top