查詢資料倉儲

已完成

當資料倉儲中的維度和事實資料表已載入資料時,您可以使用 SQL 來查詢資料表,並分析其包含的資料。 在 Synapse 專用 SQL 集區中用來查詢資料表的 Transact-SQL 語法,類似於在 SQL Server 或 Azure SQL Database 中使用的 SQL。

依維度屬性彙總量值

大多數使用資料倉儲進行的資料分析,都涉及依維度資料表中的屬性來彙總事實資料表中的數值量值。 由於實作星型或雪花式結構描述的方式,因此,執行這類彙總的查詢依賴 JOIN 子句來將事實資料表連線到維度資料表,以及彙總函式和 GROUP BY 子句的組合來定義彙總階層。

例如,下列 SQL 會查詢假設性資料倉儲中的 FactSalesDimDate 資料表,依年度和季度彙總銷售量:

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;

此查詢的結果可能看起來類似下表:

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
... ... ...

您可以視需要聯結多個維度資料表,以計算所需的彙總。 例如,下列程式碼會擴充上一個範例,根據 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;

這次,結果會包含每個城市每季的銷售總額:

CalendarYear CalendarQuarter 縣/市 TotalSales
2020 1 阿姆斯特丹 5982.53
2020 1 柏林 2826.98
2020 1 芝加哥 5372.72
... ... ... ..
2020 2 阿姆斯特丹 7163.93
2020 2 柏林 8191.12
2020 2 芝加哥 2428.72
... ... ... ..
2020 3 阿姆斯特丹 7261.92
2020 3 柏林 4202.65
2020 3 芝加哥 2287.87
... ... ... ..
2020 4 阿姆斯特丹 8262.73
2020 4 柏林 5373.61
2020 4 芝加哥 7726.23
... ... ... ..
2021 1 阿姆斯特丹 7261.28
2021 1 柏林 3648.28
2021 1 芝加哥 1027.27
... ... ... ..

雪花式結構描述中的聯結

使用雪花式結構描述時,維度可能會部分正規化;需要多個聯結,才能讓事實資料表與雪花式維度相關。 例如,假設您的資料倉儲包含 DimProduct 維度資料表,其中產品類別已正規化為個別的 DimCategory 資料表。 依產品類別彙總已售出項目的查詢可能看起來類似下列範例:

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;

此查詢的結果包括每個產品類別已售出的項目數:

ProductCategory ItemsSold
Accessories 28271
Bits and pieces 5368
... ...

注意

適用於 FactSalesDimProduct 以及適用於 DimProductDimCategory 的 JOIN 子句都是必要的,即使查詢不會從 DimProduct 傳回任何欄位也一樣。

使用次序函數

另一種常見的分析查詢是根據維度屬性來分割結果,並為每個分割區內的結果「排名」。 例如,您可能希望每年依商店的銷售營收來對商店進行排名。 若要達成此目標,您可以使用 Transact-SQL 的「次序」函數,例如 ROW_NUMBERRANKDENSE_RANKNTILE。 這些函式可讓您透過類別來分割資料,每個均會傳回特定值,指出分割區內每個資料列的相對位置:

  • ROW_NUMBER 會傳回分割區內資料列的序數位置。 例如,第一個資料列編號為 1、第二個為 2,依此類推。
  • RANK 會傳回排序結果中每個資料列的排名位置。 例如,在依銷售量排序的商店分割區中,銷售量最高的商店排名為 1。 如果有多家商店的銷售量相同,其排名會一樣,而指派給後續商店的排名則會反映銷售量較高 (包括銷售量相同) 的商店數量。
  • DENSE_RANK 為分割區中資料列排名的方式與 RANK 相同,但是若有多個資料列的排名相同,後續資料列的排名位置就會略過銷售量相同者。
  • NTILE 會傳回資料列所在的指定百分位數。 例如,在依銷售量排序的商店分割區中,NTILE(4) 會傳回商店銷售量所在的四分位數。

例如,請考慮下列查詢:

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;

查詢會根據其類別來將產品分割為群組,並在每個類別分割區中,根據產品定價來決定每個產品的相對位置。 此查詢的結果可能看起來類似下表:

ProductCategory ProductName ListPrice RowNumber 順位 DenseRank Quartile
Accessories Widget 8.99 1 1 1 1
Accessories Knicknak 8.49 2 2 2 1
Accessories Sprocket 5.99 3 3 3 2
Accessories Doodah 5.99 4 3 3 2
Accessories Spangle 2.99 5 5 4 3
Accessories Badabing 0.25 6 6 5 4
Bits and pieces Flimflam 7.49 1 1 1 1
Bits and pieces Snickity wotsit 6.99 2 2 2 1
Bits and pieces Flange 4.25 3 3 3 2
... ... ... ... ... ... ...

注意

範例結果示範 RANKDENSE_RANK 之間的差異。 請注意,在 [Accessories] 類別中,SprocketDoodah 產品具有相同定價,且都排名為價格第三高的產品。 下一個次高價格產品的 RANK 為 5 (有四個產品的價格超過它),且 DENSE_RANK 為 4 (有三個較高的價格)。

若要深入了解次序函數,請參閱 Azure Synapse Analytics 文件中的次序函數 (Transact-SQL)

擷取近似計數

儘管資料倉儲的用途主要是支援企業的分析資料模型和報表;資料分析師和資料科學家通常需要執行一些初始資料探索,就只是為了判斷資料的基本規模和分佈。

例如,下列查詢使用 COUNT 函式來擷取假設性資料倉儲中每年的銷售量:

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;

此查詢的結果可能看起來類似下表:

CalendarYear 訂單
2019 239870
2020 284741
2021 309272
... ...

資料倉儲中的資料量可能意味著,即使是計算符合指定準則之記錄數目的簡單查詢,可能也需要相當長的時間來執行。 在許多情況下,不需要準確的計數,近似的估計值就已足夠。 在這類情況下,您可以使用 APPROX_COUNT_DISTINCT 函式,如下列範例所示:

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;

APPROX_COUNT_DISTINCT 函式會使用 HyperLogLog 演算法來擷取近似計數。 保證結果的最大錯誤率為 2% 且機率為 97%,因此,使用與之前相同的假設性資料進行的查詢結果可能看起來類似下表:

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

計數較不正確,但仍足以大致比較每年銷售量。 具有大量資料時,使用 APPROX_COUNT_DISTINCT 函式的查詢會更快完成,而降低的正確性可能是在基本資料探索期間可接受的取捨。

注意

如需詳細資訊,請參閱 APPROX_COUNT_DISTINCT 函式文件。