W tym artykule zbadamy, kiedy i jak używać klauzuli SQL PARTITION BY i porównamy ją z klauzulą GROUP BY.
Zrozumienie funkcji okna
Użytkownicy bazy danych używają funkcji agregujących, takich jak MAX(), MIN(), AVERAGE() i COUNT() do wykonywania analizy danych. Funkcje te działają na całej tabeli i zwracają pojedyncze zagregowane dane przy użyciu klauzuli GROUP BY. Czasami wymagamy zagregowanych wartości w małym zestawie wierszy. W takim przypadku funkcja Window w połączeniu z funkcją agregującą pomaga osiągnąć pożądany wynik. Funkcja Window używa klauzuli OVER() i może zawierać następujące funkcje:
- Podział według: Dzieli to wiersze lub zestaw wyników zapytania na małe partycje.
- Zamów przez: To porządkuje wiersze w porządku rosnącym lub malejącym dla okna partycji. Domyślna kolejność rośnie.
- Wiersz lub zakres: Możesz dodatkowo ograniczyć wiersze w partycji, określając punkt początkowy i końcowy.
W tym artykule skupimy się na eksploracji klauzuli SQL PARTITION BY.
Przygotowywanie przykładowych danych
Załóżmy, że mamy tabelę [SalesLT].[Orders], która przechowuje szczegóły zamówień klientów. Ma kolumnę [Miasto], która określa miasto klienta, w którym złożono zamówienie.
CREATE TABLE [SalesLT].[Orders] ( orderid INT, orderdate DATE, customerName VARCHAR(100), City VARCHAR(50), amount MONEY ) INSERT INTO [SalesLT].[Orders] SELECT 1,'01/01/2021','Mohan Gupta','Alwar',10000 UNION ALL SELECT 2,'02/04/2021','Lucky Ali','Kota',20000 UNION ALL SELECT 3,'03/02/2021','Raj Kumar','Jaipur',5000 UNION ALL SELECT 4,'04/02/2021','Jyoti Kumari','Jaipur',15000 UNION ALL SELECT 5,'05/03/2021','Rahul Gupta','Jaipur',7000 UNION ALL SELECT 6,'06/04/2021','Mohan Kumar','Alwar',25000 UNION ALL SELECT 7,'07/02/2021','Kashish Agarwal','Alwar',15000 UNION ALL SELECT 8,'08/03/2021','Nagar Singh','Kota',2000 UNION ALL SELECT 9,'09/04/2021','Anil KG','Alwar',1000 Go
Załóżmy, że chcemy poznać całkowitą wartość zamówień według lokalizacji (miasto). W tym celu używamy funkcji SUM() i GROUP BY, jak pokazano poniżej.
SELECT City AS CustomerCity ,sum(amount) AS totalamount FROM [SalesLT].[Orders] GROUP BY city ORDER BY city
W zestawie wyników nie możemy używać kolumn niezwiązanych z agregacją w instrukcji SELECT. Na przykład nie możemy wyświetlić [Nazwa klienta] w danych wyjściowych, ponieważ nie jest ona uwzględniona w klauzuli GROUP BY.
SQL Server wyświetla następujący komunikat o błędzie, jeśli spróbujesz użyć kolumny niezagregowanej na liście kolumn.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount FROM [SalesLT].[Orders]
Jak pokazano poniżej, klauzula PARTITION BY tworzy mniejsze okno (zestaw wierszy danych), wykonuje agregację i wyświetla ją. W tym wyniku możesz również wyświetlić kolumny bez agregacji.
Podobnie możesz użyć funkcji AVG(), MIN(), MAX() do obliczenia średniej, minimalnej i maksymalnej kwoty z wierszy w oknie.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount, Avg(amount) OVER(PARTITION BY city) AvgOrderAmount, Min(amount) OVER(PARTITION BY city) MinOrderAmount, MAX(amount) OVER(PARTITION BY city) MaxOrderAmount FROM [SalesLT].[Orders]
Korzystanie z klauzuli SQL PARTITION BY z funkcją ROW_NUMBER()
Wcześniej otrzymywaliśmy zagregowane wartości w oknie za pomocą klauzuli PARTITION BY. Załóżmy, że zamiast sumy, potrzebujemy sumarycznej sumy w partycji.
Łączna suma działa w następujący sposób.
Wiersz | Suma skumulowana |
1 | Rank 1+ 2 |
2 | Rank 2+3 |
3 | Rank 3+4 |
Pozycja wiersza jest obliczana za pomocą funkcji ROW_NUMBER(). Najpierw użyjmy tej funkcji i zobaczmy rankingi wierszy.
- Funkcja ROW_NUMBER() używa klauzul OVER i PARTITION BY i sortuje wyniki w porządku rosnącym lub malejącym. Rozpoczyna ranking wierszy od 1 według kolejności sortowania.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number] FROM [SalesLT].[Orders]
Na przykład w mieście [Alwar] wiersz z najwyższą kwotą (25000.00) znajduje się w wierszu 1. Jak pokazano poniżej, szereguje wiersze w oknie określonym przez klauzulę PARTITION BY. Na przykład mamy trzy różne miasta [Alwar], [Jaipur] i [Kota], a każde okno (miasto) otrzymuje swoją rangę wierszy.
Aby obliczyć łączną sumę, używamy następujących argumentów.
- BIEŻĄCY WIERSZ:Określa punkt początkowy i końcowy w określonym zakresie.
- 1 następujący:określa liczbę wierszy (1), które mają nastąpić od bieżącego wiersza.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS CumulativeSUM FROM [SalesLT].[Orders]
Poniższy obrazek pokazuje, że otrzymujesz łączną sumę zamiast sumy całkowitej w oknie określonym przez klauzulę PARTITION BY.
Jeśli użyjemy ROWS UNBOUNDED PRECEDING w klauzuli SQL PARTITION BY oblicza skumulowaną sumę w następujący sposób. Używa bieżących wierszy wraz z wierszami o najwyższych wartościach w określonym oknie.
Wiersz | Suma skumulowana |
1 | Rank 1 |
2 | Rank 1+2 |
3 | Rank 1+2+3 |
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS UNBOUNDED PRECEDING) AS CumulativeSUM FROM [SalesLT].[Orders]
Porównanie klauzuli GROUP BY i SQL PARTITION BY
GRUPUJ WG | PARTYCJA PRZEZ |
Zwraca jeden wiersz na grupę po obliczeniu wartości zagregowanych. | Zwraca wszystkie wiersze z instrukcji SELECT wraz z dodatkowymi kolumnami zagregowanych wartości. |
Nie możemy użyć kolumny niezagregowanej w instrukcji SELECT. | Możemy użyć wymaganych kolumn w instrukcji SELECT i nie powoduje to żadnych błędów dla kolumny niezagregowanej. |
Wymaga użycia klauzuli HAVING do filtrowania rekordów z instrukcji SELECT. | Funkcja PARTITION może mieć dodatkowe predykaty w klauzuli WHERE oprócz kolumn użytych w instrukcji SELECT. |
GRUPA WG jest używana w zwykłych agregatach. | PARTITION BY jest używany w agregatach okienkowych. |
Nie możemy go używać do obliczania numerów wierszy lub ich rang. | Może obliczać numery wierszy i ich rangi w mniejszym oknie. |
Oddanie go do użytku
Zaleca się używanie klauzuli SQL PARTITION BY podczas pracy z wieloma grupami danych dla zagregowanych wartości w poszczególnych grupach. Podobnie można go użyć do przeglądania oryginalnych wierszy z dodatkową kolumną zagregowanych wartości.