Wykonywanie zapytań względem magazynu danych

Ukończone

Gdy tabele wymiarów i faktów w magazynie danych zostały załadowane z danymi, możesz użyć języka SQL do wykonywania zapytań dotyczących tabel i analizowania danych, które zawierają. Składnia języka Transact-SQL używana do wykonywania zapytań dotyczących tabel w dedykowanej puli SQL usługi Synapse jest podobna do języka SQL używanego w programie SQL Server lub usłudze Azure SQL Database.

Agregowanie miar według atrybutów wymiaru

Większość analiz danych w magazynie danych obejmuje agregowanie miar liczbowych w tabelach faktów według atrybutów w tabelach wymiarów. Ze względu na sposób implementacji schematu gwiazdy lub płatka śniegu zapytania do wykonywania tego rodzaju agregacji polegają na JOIN klauzulach łączących tabele faktów z tabelami wymiarów oraz kombinację funkcji agregujących i GROUP BY klauzul w celu zdefiniowania hierarchii agregacji.

Na przykład następujące dane SQL wysyła zapytania do tabel FactSales i DimDate w hipotetycznym magazynie danych w celu agregowania kwot sprzedaży według roku i kwartału:

SELECT  dates.CalendarYear,
        dates.CalendarQuarter,
        SUM(sales.SalesAmount) AS TotalSales
FROM dbo.FactSales AS sales
JOIN dbo.DimDate AS dates ON sales.OrderDateKey = dates.DateKey
GROUP BY dates.CalendarYear, dates.CalendarQuarter
ORDER BY dates.CalendarYear, dates.CalendarQuarter;

Wyniki tego zapytania będą wyglądać podobnie do poniższej tabeli:

CalendarYear CalendarQuarter TotalSales
2020 1 25980.16
2020 2 27453.87
2020 3 28527.15
2020 100 31083.45
2021 1 34562.96
2021 2 36162.27
... ... ...

Możesz połączyć dowolną liczbę tabel wymiarów, aby obliczyć potrzebne agregacje. Na przykład poniższy kod rozszerza poprzedni przykład, aby podzielić kwartalne sumy sprzedaży według miasta na podstawie szczegółów adresu klienta w tabeli DimCustomer :

SELECT  dates.CalendarYear,
        dates.CalendarQuarter,
        custs.City,
        SUM(sales.SalesAmount) AS TotalSales
FROM dbo.FactSales AS sales
JOIN dbo.DimDate AS dates ON sales.OrderDateKey = dates.DateKey
JOIN dbo.DimCustomer AS custs ON sales.CustomerKey = custs.CustomerKey
GROUP BY dates.CalendarYear, dates.CalendarQuarter, custs.City
ORDER BY dates.CalendarYear, dates.CalendarQuarter, custs.City;

Tym razem wyniki obejmują kwartalną sumę sprzedaży dla każdego miasta:

CalendarYear CalendarQuarter City TotalSales
2020 1 Amsterdam 5982.53
2020 1 Berlin 2826.98
2020 1 Chicago 5372.72
... ... ... ..
2020 2 Amsterdam 7163.93
2020 2 Berlin 8191.12
2020 2 Chicago 2428.72
... ... ... ..
2020 3 Amsterdam 7261.92
2020 3 Berlin 4202.65
2020 3 Chicago 2287.87
... ... ... ..
2020 100 Amsterdam 8262.73
2020 100 Berlin 5373.61
2020 100 Chicago 7726.23
... ... ... ..
2021 1 Amsterdam 7261.28
2021 1 Berlin 3648.28
2021 1 Chicago 1027.27
... ... ... ..

Sprzężenia w schemacie płatka śniegu

W przypadku korzystania ze schematu płatka śniegu wymiary mogą być częściowo znormalizowane; wymaganie wielu sprzężeń w celu powiązania tabel faktów z wymiarami płatka śniegu. Załóżmy na przykład, że magazyn danych zawiera tabelę wymiarów DimProduct , z której kategorie produktów zostały znormalizowane do oddzielnej tabeli DimCategory . Zapytanie dotyczące agregowania elementów sprzedanych według kategorii produktów może wyglądać podobnie do poniższego przykładu:

SELECT  cat.ProductCategory,
        SUM(sales.OrderQuantity) AS ItemsSold
FROM dbo.FactSales AS sales
JOIN dbo.DimProduct AS prod ON sales.ProductKey = prod.ProductKey
JOIN dbo.DimCategory AS cat ON prod.CategoryKey = cat.CategoryKey
GROUP BY cat.ProductCategory
ORDER BY cat.ProductCategory;

Wyniki tego zapytania obejmują liczbę sprzedanych przedmiotów dla każdej kategorii produktów:

ProductCategory ElementyPrzedaj
Akcesoria 28271
Bity i kawałki 5368
... ...

Uwaga

Klauzule JOIN dla tabel FactSales i DimProduct oraz DimProduct i DimCategory są wymagane, mimo że żadne pola z DimProduct nie są zwracane przez zapytanie.

Korzystanie z funkcji klasyfikacji

Innym typowym rodzajem zapytania analitycznego jest partycjonowanie wyników na podstawie atrybutu wymiaru i klasyfikacja wyników w ramach każdej partycji. Na przykład możesz chcieć sklasyfikować sklepy każdego roku według przychodów ze sprzedaży. Aby osiągnąć ten cel, możesz użyć funkcji klasyfikacji języka Transact-SQL, takich jak ROW_NUMBER, RANK, DENSE_RANKi NTILE. Te funkcje umożliwiają partycjonowanie danych na kategorie, z których każda zwraca określoną wartość, która wskazuje względną pozycję każdego wiersza w partycji:

  • ROW_NUMBER zwraca położenie porządkowe wiersza w partycji. Na przykład pierwszy wiersz jest numerowany 1, drugi 2 itd.
  • Funkcja RANK zwraca pozycję sklasyfikowaną każdego wiersza w uporządkowanych wynikach. Na przykład w partycji sklepów uporządkowanych według wielkości sprzedaży magazyn o najwyższej wielkości sprzedaży jest w rankingu 1. Jeśli wiele sklepów ma te same woluminy sprzedaży, zostaną one sklasyfikowane tak samo, a ranga przypisana do kolejnych sklepów odzwierciedla liczbę sklepów, które mają wyższe wolumeny sprzedaży - w tym więzi.
  • DENSE_RANK umieszcza wiersze w partycji w taki sam sposób jak RANK, ale jeśli wiele wierszy ma tę samą rangę, kolejne wiersze są pozycjami klasyfikacji ignorują powiązania.
  • FUNKCJA NTILE zwraca określony percentyl, w którym wiersz spada. Na przykład w partycji sklepów uporządkowanych według wielkości sprzedaży zwraca kwartyl, NTILE(4) w którym znajduje się wielkość sprzedaży sklepu.

Rozważmy na przykład następujące zapytanie:

SELECT  ProductCategory,
        ProductName,
        ListPrice,
        ROW_NUMBER() OVER
            (PARTITION BY ProductCategory ORDER BY ListPrice DESC) AS RowNumber,
        RANK() OVER
            (PARTITION BY ProductCategory ORDER BY ListPrice DESC) AS Rank,
        DENSE_RANK() OVER
            (PARTITION BY ProductCategory ORDER BY ListPrice DESC) AS DenseRank,
        NTILE(4) OVER
            (PARTITION BY ProductCategory ORDER BY ListPrice DESC) AS Quartile
FROM dbo.DimProduct
ORDER BY ProductCategory;

Zapytanie dzieli produkty na grupy na podstawie ich kategorii, a w ramach każdej partycji kategorii względna pozycja każdego produktu jest określana na podstawie ceny katalogowej. Wyniki tego zapytania mogą wyglądać podobnie do poniższej tabeli:

ProductCategory ProductName ListPrice Rownumber Ranga DenseRank Kwartyl
Akcesoria Widget 8.99 1 1 1 1
Akcesoria Knicknak 8.49 2 2 2 1
Akcesoria Zębatki 5,99 3 3 3 2
Akcesoria Doodah 5,99 100 3 3 2
Akcesoria Spangle 2,99 5 5 100 3
Akcesoria Badabing 0.25 6 6 5 100
Bity i kawałki Flimflam 7.49 1 1 1 1
Bity i kawałki Snickity wotsit 6.99 2 2 2 1
Bity i kawałki Kołnierz 4.25 3 3 3 2
... ... ... ... ... ... ...

Uwaga

W przykładowych wynikach pokazano różnicę między elementami RANK i DENSE_RANK. Należy pamiętać, że w kategorii Akcesoria produkty Sprocket i Doodah mają taką samą cenę, a oba są klasyfikowane jako trzeci najwyższy produkt. Następny najwyższy produkt ma rangę 5 (są cztery produkty droższe niż) i DENSE_RANK 4 (są trzy wyższe ceny).

Aby dowiedzieć się więcej na temat funkcji klasyfikacji, zobacz Ranking Functions (Transact-SQL) w dokumentacji usługi Azure Synapse Analytics.

Pobieranie przybliżonej liczby

Chociaż celem magazynu danych jest przede wszystkim obsługa modeli danych analitycznych i raportów dla przedsiębiorstwa; analitycy danych i analitycy danych często muszą przeprowadzić początkową eksplorację danych, aby określić podstawową skalę i rozkład danych.

Na przykład następujące zapytanie używa COUNT funkcji do pobierania liczby sprzedaży dla każdego roku w hipotetycznym magazynie danych:

SELECT dates.CalendarYear AS CalendarYear,
    COUNT(DISTINCT sales.OrderNumber) AS Orders
FROM FactSales AS sales
JOIN DimDate AS dates ON sales.OrderDateKey = dates.DateKey
GROUP BY dates.CalendarYear
ORDER BY CalendarYear;

Wyniki tego zapytania mogą wyglądać podobnie do poniższej tabeli:

CalendarYear Zamówienia
2019 239870
2020 284741
2021 309272
... ...

Ilość danych w magazynie danych może oznaczać, że nawet proste zapytania do zliczenia liczby rekordów spełniających określone kryteria mogą zająć dużo czasu. W wielu przypadkach dokładna liczba nie jest wymagana — przybliżone oszacowanie wystarczy. W takich przypadkach można użyć APPROX_COUNT_DISTINCT funkcji, jak pokazano w poniższym przykładzie:

SELECT dates.CalendarYear AS CalendarYear,
    APPROX_COUNT_DISTINCT(sales.OrderNumber) AS ApproxOrders
FROM FactSales AS sales
JOIN DimDate AS dates ON sales.OrderDateKey = dates.DateKey
GROUP BY dates.CalendarYear
ORDER BY CalendarYear;

Funkcja APPROX_COUNT_DISTINCT używa algorytmu HyperLogLog, aby pobrać przybliżoną liczbę. Wynik ma gwarancję maksymalnej szybkości błędów wynoszącej 2% z prawdopodobieństwem 97%, więc wyniki tego zapytania z tymi samymi hipotetycznymi danymi, jak poprzednio, mogą wyglądać podobnie do poniższej tabeli:

CalendarYear Przybliżone zamówienia
2019 235552
2020 290436
2021 304633
... ...

Liczby są mniej dokładne, ale nadal wystarczające do przybliżonego porównania sprzedaży rocznej. W przypadku dużej ilości danych zapytanie korzystające z APPROX_COUNT_DISTINCT funkcji kończy się szybciej, a zmniejszona dokładność może być akceptowalnym kompromisem podczas podstawowej eksploracji danych.

Uwaga

Aby uzyskać więcej informacji, zobacz dokumentację funkcji APPROX_COUNT_DISTINCT .