Wie der Titel schon sagt, brauche ich etwas Hilfe, um eine laufende Summe in T-SQL zu erhalten. Das Problem ist, dass die Summe, die ich machen muss, die Summe einer Zählung ist:
sum(count (distinct (customers)))
Sagen Sie, wenn ich die Zählung alleine durchführe, wäre das Ergebnis:
Day | CountCustomers
----------------------
5/1 | 1
5/2 | 0
5/3 | 5
Ich brauche die Ausgabe mit der Summe zu sein:
Day | RunningTotalCustomers
----------------------
5/1 | 1
5/2 | 1
5/3 | 6
Ich habe vor der Verwendung der coalesce
Methode Summen ausgeführt , aber nie mit einer Zählung. Ich bin nicht sicher, wie ich es jetzt machen soll, da ich die Zählung habe.
sql-server
t-sql
Aaron Bertrand
quelle
quelle
Day
ein Schlüssel, und sind die Werte zusammenhängend?Antworten:
Hier sind einige Methoden, die Sie vergleichen können. Lassen Sie uns zuerst eine Tabelle mit Dummy-Daten erstellen. Ich fülle dies mit einer Reihe zufälliger Daten aus sys.all_columns. Nun, es ist irgendwie zufällig - ich stelle sicher, dass die Daten zusammenhängend sind (was wirklich nur für eine der Antworten wichtig ist).
Ergebnisse:
Die Daten sehen wie folgt aus (5000 Zeilen) - sehen jedoch auf Ihrem System je nach Version und Build-Nr .:
Die Ergebnisse der laufenden Summen sollten wie folgt aussehen (501 Zeilen):
Die Methoden, die ich vergleichen werde, sind:
selbst beitreten
Auf diese Weise werden Sie aufgefordert, dies zu tun, wenn Sie gewarnt werden, sich von Cursorn fernzuhalten, da "satzbasiert immer schneller ist". In einigen kürzlich durchgeführten Experimenten habe ich festgestellt, dass der Cursor diese Lösung übertrifft.
rekursives cte mit Daten
Erinnerung - Dies basiert auf zusammenhängenden Daten (keine Lücken), bis zu 10000 Rekursionsebenen und darauf, dass Sie das Startdatum des gewünschten Bereichs kennen (um den Anker zu setzen). Sie könnten den Anker natürlich mithilfe einer Unterabfrage dynamisch setzen, aber ich wollte die Dinge einfach halten.
rekursives cte mit row_number
Die Berechnung der Zeilennummer ist hier etwas teuer. Dies unterstützt wieder die maximale Rekursionsstufe von 10000, aber Sie müssen den Anker nicht zuweisen.
rekursives cte mit temporärer Tabelle
Wie vorgeschlagen, aus Mikaels Antwort stehlen, um dies in die Tests einzubeziehen.
schrulliges Update
Wiederum beziehe ich dies nur der Vollständigkeit halber ein; Ich persönlich würde mich nicht auf diese Lösung verlassen, da, wie ich bereits in einer anderen Antwort erwähnt habe, diese Methode nicht garantiert funktioniert und möglicherweise in einer zukünftigen Version von SQL Server völlig kaputt geht. (Ich gebe mein Bestes, um SQL Server dazu zu zwingen, die von mir gewünschte Reihenfolge einzuhalten, wobei ich einen Hinweis für die Indexauswahl verwende.)
Mauszeiger
"Vorsicht, hier gibt es Cursor! Cursor sind böse! Sie sollten Cursor um jeden Preis meiden!" Nein, das rede ich nicht, ich höre nur viel. Entgegen der landläufigen Meinung gibt es einige Fälle, in denen Cursor angebracht sind.
SQL Server 2012
Wenn Sie mit der neuesten Version von SQL Server arbeiten, können wir durch Verbesserungen der Fensterfunktionen die laufenden Summen auf einfache Weise berechnen, ohne die exponentiellen Kosten für die Selbstverknüpfung (die Summe wird in einem Durchgang berechnet) und die Komplexität der CTEs (einschließlich der Anforderung) zusammenhängender Zeilen für eine bessere Leistung des CTE), das nicht unterstützte eigenartige Update und den verbotenen Cursor. Achten Sie nur auf den Unterschied zwischen der Verwendung von
RANGE
undROWS
oder darauf, dass Sie überhaupt nichts angeben - diesROWS
vermeidet nur eine Spool-Funktion auf der Festplatte, die ansonsten die Leistung erheblich beeinträchtigt.Leistungsvergleiche
Ich verfolgte jeden Ansatz und wickelte ihn wie folgt in eine Charge ein:
Hier sind die Ergebnisse der Gesamtdauer in Millisekunden (denken Sie daran, dass dies jedes Mal auch die DBCC-Befehle einschließt):
Und ich habe es wieder ohne die DBCC-Befehle gemacht:
Entfernen Sie sowohl den DBCC als auch die Schleifen, indem Sie nur eine rohe Iteration messen:
Schließlich multiplizierte ich die Zeilenzahl in der Quelltabelle mit 10 (indem ich die Spitze auf 50000 änderte und eine weitere Tabelle als Cross-Join hinzufügte). Das Ergebnis ist eine einzige Iteration ohne DBCC-Befehle (einfach aus Zeitgründen):
Ich habe nur die Dauer gemessen - ich überlasse es dem Leser als Übung, diese Ansätze mit ihren Daten zu vergleichen und andere Metriken zu vergleichen, die wichtig sein können (oder mit ihrem Schema / ihren Daten variieren können). Bevor Sie aus dieser Antwort Schlussfolgerungen ziehen, müssen Sie sie anhand Ihrer Daten und Ihres Schemas testen. Diese Ergebnisse werden sich mit ziemlicher Sicherheit ändern, je höher die Zeilenanzahl ist.
Demo
Ich habe eine SQLFiddle hinzugefügt . Ergebnisse:
Fazit
In meinen Tests wäre die Wahl:
Aber auch hier sollten Sie diese anhand Ihres Schemas und Ihrer Daten testen. Da dies ein erfundener Test mit relativ geringen Reihenzahlen war, kann es auch ein Furz im Wind sein. Ich habe andere Tests mit unterschiedlichen Schemata und Zeilenzahlen durchgeführt und die Performance-Heuristiken waren sehr unterschiedlich. Deshalb habe ich so viele Folgefragen zu Ihrer ursprünglichen Frage gestellt.
AKTUALISIEREN
Ich habe hier mehr darüber gebloggt:
Beste Ansätze zum Ausführen von Summen - aktualisiert für SQL Server 2012
quelle
Dies ist anscheinend die optimale Lösung
quelle
day
.Nur ein anderer Weg, teuer, aber versionsunabhängig. Es werden keine temporären Tabellen oder Variablen verwendet.
quelle