Fråga ett informationslager

Slutförd

När dimensions- och faktatabellerna i ett informationslager har lästs in med data kan du använda SQL för att köra frågor mot tabellerna och analysera de data de innehåller. Transact-SQL-syntaxen som används för att fråga efter tabeller i en synapse-dedikerad SQL-pool liknar SQL som används i SQL Server eller Azure SQL Database.

Aggregera mått efter dimensionsattribut

De flesta dataanalyser med ett informationslager omfattar aggregering av numeriska mått i faktatabeller efter attribut i dimensionstabeller. På grund av hur ett star- eller snowflake-schema implementeras förlitar sig frågor för att utföra den här typen av aggregering på JOIN satser för att ansluta faktatabeller till dimensionstabeller och en kombination av aggregerade funktioner och GROUP BY satser för att definiera aggregeringshierarkierna.

Följande SQL frågar till exempel tabellerna FactSales och DimDate i ett hypotetiskt informationslager för att aggregera försäljningsbelopp per år och kvartal:

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;

Resultatet från den här frågan skulle se ut ungefär som i följande tabell:

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

Du kan ansluta så många dimensionstabeller som behövs för att beräkna de sammansättningar du behöver. Följande kod utökar till exempel föregående exempel för att dela upp de kvartalsvisa försäljningssummorna per stad baserat på kundens adressinformation i tabellen 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;

Den här gången innehåller resultatet en kvartalsvis försäljningssumma för varje stad:

CalendarYear CalendarQuarter Ort 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 4 Amsterdam 8262.73
2020 4 Berlin 5373.61
2020 4 Chicago 7726.23
... ... ... ..
2021 1 Amsterdam 7261.28
2021 1 Berlin 3648.28
2021 1 Chicago 1027.27
... ... ... ..

Ansluter till ett snowflake-schema

När du använder ett snowflake-schema kan dimensioner delvis normaliseras. kräver flera kopplingar för att relatera faktatabeller till snowflake-dimensioner. Anta till exempel att ditt informationslager innehåller en DimProduct-dimensionstabell från vilken produktkategorierna har normaliserats till en separat DimCategory-tabell . En fråga för att aggregera objekt som säljs efter produktkategori kan se ut ungefär som i följande exempel:

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;

Resultatet från den här frågan inkluderar antalet sålda objekt för varje produktkategori:

ProductCategory ObjektSålda
Accessoarer 28271
Bitar och bitar 5368
... ...

Kommentar

JOIN-satser för FactSales och DimProduct och dimproduct och DimCategory krävs, även om inga fält från DimProduct returneras av frågan.

Använda rangordningsfunktioner

En annan vanlig typ av analysfråga är att partitioneras resultaten baserat på ett dimensionsattribut och rangordna resultaten inom varje partition. Du kanske till exempel vill rangordna butiker varje år efter deras försäljningsintäkter. För att uppnå det här målet kan du använda Transact-SQL-rankningsfunktioner som ROW_NUMBER, RANK, DENSE_RANKoch NTILE. Med de här funktionerna kan du partitionera data över kategorier, var och en returnerar ett specifikt värde som anger den relativa positionen för varje rad i partitionen:

  • ROW_NUMBER returnerar ordningstalet för raden i partitionen. Till exempel är den första raden numrerad 1, den andra 2 och så vidare.
  • RANK returnerar den rangordnade positionen för varje rad i de ordnade resultaten. I en partition av butiker som sorteras efter försäljningsvolym rangordnas till exempel butiken med den högsta försäljningsvolymen 1. Om flera butiker har samma försäljningsvolymer rangordnas de på samma sätt och rangordningen som tilldelas efterföljande butiker återspeglar antalet butiker som har högre försäljningsvolymer – inklusive band.
  • DENSE_RANK rangordnar rader i en partition på samma sätt som RANK, men när flera rader har samma rangordning ignoreras banden i efterföljande rader.
  • NTILE returnerar den angivna percentilen där raden faller. I en partition av butiker som sorteras efter försäljningsvolym NTILE(4) returnerar till exempel kvartilen där en butiks försäljningsvolym placerar den.

Tänk dig följande fråga:

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;

Frågan partitionerar produkter i grupper baserat på deras kategorier, och inom varje kategoripartition bestäms den relativa positionen för varje produkt baserat på listpriset. Resultatet från den här frågan kan se ut ungefär som i följande tabell:

ProductCategory ProductName ListPrice Radnummer Rangordning DenseRank Kvartil
Accessoarer Widget 8.99 1 1 1 1
Accessoarer Knicknak 8.49 2 2 2 1
Accessoarer Sprocket 5.99 3 3 3 2
Accessoarer Doodah 5.99 4 3 3 2
Accessoarer Spangle 2.99 5 5 4 3
Accessoarer Badabing 0.25 6 6 5 4
Bitar och bitar Flimflam 7.49 1 1 1 1
Bitar och bitar Snickity wotsit 6.99 2 2 2 1
Bitar och bitar Fläns 4.25 3 3 3 2
... ... ... ... ... ... ...

Kommentar

Exempelresultaten visar skillnaden mellan RANK och DENSE_RANK. Observera att i kategorin Tillbehör har Sprocket- och Doodah-produkterna samma listpris och är båda rankade som den tredje högst prissatta produkten. Den näst högst prissatta produkten har en RANK på 5 (det finns fyra produkter dyrare än den) och en DENSE_RANK på 4 (det finns tre högre priser).

Mer information om rangordningsfunktioner finns i Rankningsfunktioner (Transact-SQL) i dokumentationen för Azure Synapse Analytics.

Hämtar ett ungefärligt antal

Syftet med ett informationslager är främst att stödja analysdatamodeller och rapporter för företaget. dataanalytiker och dataforskare behöver ofta utföra viss inledande datautforskning, bara för att fastställa den grundläggande skalan och distributionen av data.

Följande fråga använder COUNT till exempel funktionen för att hämta antalet försäljningar för varje år i ett hypotetiskt informationslager:

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;

Resultatet av den här frågan kan se ut ungefär som i följande tabell:

CalendarYear Ordrar
2019 239870
2020 284741
2021 309272
... ...

Mängden data i ett informationslager kan innebära att även enkla frågor för att räkna antalet poster som uppfyller angivna kriterier kan ta lång tid att köra. I många fall krävs inte ett exakt antal – en ungefärlig uppskattning räcker. I sådana fall kan du använda APPROX_COUNT_DISTINCT funktionen enligt följande exempel:

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;

Funktionen APPROX_COUNT_DISTINCT använder en HyperLogLog-algoritm för att hämta ett ungefärligt antal. Resultatet kommer garanterat att ha en maximal felfrekvens på 2 % med 97 % sannolikhet, så resultatet av den här frågan med samma hypotetiska data som tidigare kan se ut ungefär som i följande tabell:

CalendarYear ApproxOrders
2019 235552
2020 290436
2021 304633
... ...

Antalet är mindre exakt, men räcker fortfarande för en ungefärlig jämförelse av den årliga försäljningen. Med en stor mängd data slutförs frågan med APPROX_COUNT_DISTINCT funktionen snabbare och den minskade noggrannheten kan vara en acceptabel kompromiss under grundläggande datautforskning.

Kommentar

Mer information finns i dokumentationen om APPROX_COUNT_DISTINCT funktion.