Przejdź do treści
FullstackDev

Funkcje okienne agregujące

Funkcje okienne agregujące są jednym z najważniejszych narzędzi w analizie danych. Pozwalają one na obliczanie wartości funkcji agregujących na podzbiorach danych, które są zdefiniowane przez okno. Okno to zbiór wierszy, które są grupowane na podstawie określonych kryteriów. Funkcje agregujące, takie jak: SUM(), AVG(), MIN(), MAX(), COUNT() są obliczane dla każdego okna z osobna.

Tak więc, o ile w danym zapytaniu zwracamy informacje, które chcielibyśmy dodatkowo przetworzyć, to zamiast używania podzapytań, możemy wykorzystać funkcje okna, aby uzyskać te informacje w jednym zapytaniu.

SUM()

Funkcja SUM() oblicza sumę wartości w kolumnie. W przypadku funkcji okiennej SUM() wartości są sumowane dla każdego okna z osobna.

Przykładowo, mając bazowę zapytanie z tabeli SalesLT.SalesOrderDetail:

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice
FROM 
    SalesLT.SalesOrderDetail;

Możemy obliczyć sumę wartości w kolumnie OrderQty dla każdego zamówienia, korzystając z funkcji okiennej SUM():

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice,
    SUM(OrderQty) OVER(PARTITION BY SalesOrderID) AS OrderQtySum
FROM
    SalesLT.SalesOrderDetail;

W wyniku otrzymamy kolumnę OrderQtySum, która zawiera sumę wartości w kolumnie OrderQty dla każdego zamówienia z osobna

Podobny wynik, dostalibyśmy z poniższego zapytania:

SELECT 
    SOD.SalesOrderID,
    SOD.SalesOrderDetailID,
    SOD.OrderQty,
    UnitPrice,
    (SELECT SUM(OrderQty)
     FROM SalesLT.SalesOrderDetail SOD2
     WHERE SOD2.SalesOrderID = SOD.SalesOrderID) AS OrderQtySum
FROM
    SalesLT.SalesOrderDetail SOD;

AVG()

Funkcja AVG() oblicza średnią wartości w kolumnie. W przypadku funkcji okiennej AVG() wartości są obliczane dla każdego okna z osobna.

Przykładowo, mając bazowę zapytanie z tabeli SalesLT.SalesOrderDetail:

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice
FROM
    SalesLT.SalesOrderDetail;

Możemy obliczyć średnią wartości w kolumnie UnitPrice dla każdego zamówienia, korzystając z funkcji okiennej AVG():

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice,
    AVG(UnitPrice) OVER(PARTITION BY SalesOrderID) AS UnitPriceAvg
FROM
    SalesLT.SalesOrderDetail;

W wyniku otrzymamy kolumnę UnitPriceAvg, która zawiera średnią wartości w kolumnie UnitPrice dla każdego zamówienia z osobna.

MIN()/ MAX()

Funkcje MIN() i MAX() obliczają odpowiednio minimalną i maksymalną wartość w kolumnie. W przypadku funkcji okiennej wartości są obliczane dla każdego okna z osobna.

Przykładowo, mając bazowę zapytanie z tabeli SalesLT.SalesOrderDetail:

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice
FROM
    SalesLT.SalesOrderDetail;

Możemy obliczyć minimalną i maksymalną wartość w kolumnie UnitPrice dla każdego zamówienia, korzystając z funkcji okiennej MIN() i MAX():

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice,
    MIN(UnitPrice) OVER(PARTITION BY SalesOrderID) AS UnitPriceMin,
    MAX(UnitPrice) OVER(PARTITION BY SalesOrderID) AS UnitPriceMax
FROM
    SalesLT.SalesOrderDetail;

W wyniku otrzymamy kolumny UnitPriceMin i UnitPriceMax, które zawierają odpowiednio minimalną i maksymalną wartość w kolumnie UnitPrice dla każdego zamówienia z osobna.

COUNT()

Funkcja COUNT() oblicza liczbę wierszy w kolumnie. W przypadku funkcji okiennej wartości są obliczane dla każdego okna z osobna.

Przykładowo, mając bazowę zapytanie z tabeli SalesLT.SalesOrderDetail:

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice
FROM
    SalesLT.SalesOrderDetail;

Możemy obliczyć liczbę wierszy dla każdego zamówienia, korzystając z funkcji okiennej COUNT():

SELECT 
    SalesOrderID,
    SalesOrderDetailID,
    OrderQty,
    UnitPrice,
    COUNT(*) OVER(PARTITION BY SalesOrderID) AS OrderDetailCount
FROM
    SalesLT.SalesOrderDetail;

W wyniku otrzymamy kolumnę OrderDetailCount, która zawiera liczbę wierszy dla każdego zamówienia z osobna.

Zadanie

Wykorzystując funkcję okienną SUM, dowiedz się, ile największych sprzedaży dokonał, sprzedawca adventure-works\jae0, zanim przekroczył łączną kwotę sprzedaży (tabela: SalesOrderHeader, kolumna: SubTotal) 500 000.

Rozwiązanie
-- ROZWIĄZANIE

SELECT COUNT(*)
FROM (
    SELECT c.SalesPerson, soh.SubTotal,
        SUM(SubTotal) OVER (ORDER BY SubTotal DESC) RunningSum
    FROM SalesLT.SalesOrderHeader soh
    JOIN SalesLT.Customer c on c.CustomerID = soh.CustomerID
    WHERE c.SalesPerson = 'adventure-works\jae0'
) sub
WHERE RunningSum < 500000