Jak sugeruje tytuł, potrzebuję pomocy w uzyskaniu bieżącej sumy w języku T-SQL. Problem polega na tym, że suma, którą muszę zrobić, jest sumą liczby:
sum(count (distinct (customers)))
Powiedz, że gdybym sam wyliczył liczbę, wynik byłby następujący:
Day | CountCustomers
----------------------
5/1 | 1
5/2 | 0
5/3 | 5
Potrzebuję danych wyjściowych z sumą, która będzie:
Day | RunningTotalCustomers
----------------------
5/1 | 1
5/2 | 1
5/3 | 6
Zrobiłem sumowanie przed użyciem tej coalesce
metody, ale nigdy z liczeniem. Nie jestem pewien, jak to zrobić, skoro mam już rachubę.
sql-server
t-sql
Aaron Bertrand
źródło
źródło
Day
klucz jest, a czy wartości są ciągłe?Odpowiedzi:
Oto kilka metod, które możesz porównać. Najpierw skonfigurujmy tabelę z danymi pozorowanymi. Wypełniam to losowymi danymi z sys.all_columns. Cóż, to trochę losowe - upewniam się, że daty są ciągłe (co jest tak naprawdę ważne tylko dla jednej z odpowiedzi).
Wyniki:
Dane wyglądają tak (5000 wierszy) - ale będą wyglądać nieco inaczej w zależności od wersji i wersji #:
Wyniki sumy bieżącej powinny wyglądać tak (501 wierszy):
Metody, które zamierzam porównać to:
dołączyć do siebie
W ten sposób ludzie każą ci to robić, gdy ostrzegają, abyś trzymał się z dala od kursorów, ponieważ „oparte na zestawie jest zawsze szybsze”. W niektórych ostatnich eksperymentach odkryłem, że kursor wyprzedza to rozwiązanie.
rekurencyjne cte z datami
Przypomnienie - zależy to od ciągłych dat (bez przerw), do 10000 poziomów rekurencji oraz znajomości daty początkowej interesującego Cię zakresu (aby ustawić kotwicę). Oczywiście można dynamicznie ustawić kotwicę za pomocą podzapytania, ale chciałem, aby wszystko było proste.
rekurencyjne cte z numer_wiersza
Obliczenie numer_wiersza jest tutaj nieco drogie. Ponownie obsługuje to maksymalny poziom rekurencji wynoszący 10000, ale nie trzeba przypisywać kotwicy.
rekurencyjny cte z tabelą temp
Kradzież z odpowiedzi Mikaela, zgodnie z sugestią, aby uwzględnić to w testach.
dziwna aktualizacja
Ponownie włączam to tylko dla kompletności; Ja osobiście nie polegałbym na tym rozwiązaniu, ponieważ, jak wspomniałem w innej odpowiedzi, nie gwarantuje się, że ta metoda w ogóle zadziała i może całkowicie zepsuć się w przyszłej wersji SQL Server. (Dokładam wszelkich starań, aby zmusić program SQL Server do wykonania żądanej kolejności, korzystając ze wskazówek dotyczących wyboru indeksu).
kursor
„Uwaga, są tu kursory! Kursory są złe! Powinieneś unikać kursorów za wszelką cenę!” Nie, to nie ja mówię, to tylko rzeczy, które dużo słyszę. Wbrew powszechnej opinii kursory są odpowiednie.
SQL Server 2012
Jeśli korzystasz z najnowszej wersji programu SQL Server, ulepszenia funkcji okienkowania pozwalają nam łatwo obliczyć sumy bieżące bez wykładniczego kosztu samozłączenia (suma obliczana jest w jednym przebiegu), złożoność CTE (w tym wymaganie ciągłych wierszy dla lepszej wydajności CTE), nieobsługiwana dziwaczna aktualizacja i zabroniony kursor. Wystarczy uważać na różnicę pomiędzy użyciem
RANGE
iROWS
, lub nie określając w ogóle - tylkoROWS
unika się szpulę na dysku, która będzie utrudniać wydajność znacznie inaczej.porównania wydajności
Podjąłem każde podejście i zapakowałem je w partię, używając:
Oto wyniki całkowitego czasu trwania w milisekundach (pamiętaj, że dotyczy to również poleceń DBCC za każdym razem):
Zrobiłem to ponownie bez poleceń DBCC:
Usuwając zarówno DBCC, jak i pętle, mierząc tylko jedną surową iterację:
Na koniec pomnożyłem liczbę wierszy w tabeli źródłowej przez 10 (zmieniając górę na 50000 i dodając kolejną tabelę jako połączenie krzyżowe). Rezultaty tego, jedna iteracja bez poleceń DBCC (po prostu w interesie czasu):
Zmierzyłem tylko czas trwania - pozostawię to jako ćwiczenie dla czytelnika, aby porównać te podejścia na ich danych, porównując inne metryki, które mogą być ważne (lub mogą różnić się w zależności od schematu / danych). Zanim wyciągniesz wnioski z tej odpowiedzi, od ciebie zależy sprawdzenie jej danych i schematu ... wyniki te prawie na pewno zmienią się, gdy liczba wierszy będzie wyższa.
próbny
Dodałem sqlfiddle . Wyniki:
wniosek
W moich testach wybór byłby następujący:
Ale ponownie powinieneś przetestować je pod kątem swojego schematu i danych. Ponieważ był to wymyślony test ze stosunkowo małą liczbą rzędów, równie dobrze może to być pierd na wietrze. Przeprowadziłem inne testy z różnymi schematami i liczbą wierszy, a heurystyka wydajności była całkiem inna ... dlatego zadałem tyle pytań uzupełniających do twojego pierwotnego pytania.
AKTUALIZACJA
Napisałem o tym więcej na blogu:
Najlepsze podejścia do uruchamiania sum - zaktualizowane do SQL Server 2012
źródło
Jest to najwyraźniej optymalne rozwiązanie
źródło
day
.Po prostu inny sposób, kosztowny, ale niezależny od wersji. Nie używa tabel tymczasowych ani zmiennych.
źródło