Consultar um armazém de dados

Concluído

Quando as tabelas de dimensões e fatos em um data warehouse tiverem sido carregadas com dados, você poderá usar SQL para consultar as tabelas e analisar os dados que elas contêm. A sintaxe Transact-SQL usada para consultar tabelas em um pool SQL dedicado Synapse é semelhante ao SQL usado no SQL Server ou no Banco de Dados SQL do Azure.

Agregação de medidas por atributos de dimensão

A maioria das análises de dados com um data warehouse envolve a agregação de medidas numéricas em tabelas de fato por atributos em tabelas de dimensão. Devido à forma como um esquema de estrela ou floco de neve é implementado, as consultas para executar esse tipo de agregação dependem JOIN de cláusulas para conectar tabelas de fatos a tabelas de dimensão e uma combinação de funções agregadas e GROUP BY cláusulas para definir as hierarquias de agregação.

Por exemplo, o SQL a seguir consulta as tabelas FactSales e DimDate em um data warehouse hipotético para agregar valores de vendas por ano e trimestre:

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;

Os resultados dessa consulta seriam semelhantes à tabela a seguir:

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

Você pode unir quantas tabelas de dimensão forem necessárias para calcular as agregações necessárias. Por exemplo, o código a seguir estende o exemplo anterior para dividir os totais de vendas trimestrais por cidade com base nos detalhes de endereço do cliente na tabela 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;

Desta vez, os resultados incluem um total trimestral de vendas para cada cidade:

CalendarYear CalendarQuarter City TotalSales
2020 1 Amesterdão 5982.53
2020 1 Berlim 2826.98
2020 1 Chicago 5372.72
... ... ... ..
2020 2 Amesterdão 7163.93
2020 2 Berlim 8191.12
2020 2 Chicago 2428.72
... ... ... ..
2020 3 Amesterdão 7261.92
2020 3 Berlim 4202.65
2020 3 Chicago 2287.87
... ... ... ..
2020 4 Amesterdão 8262.73
2020 4 Berlim 5373.61
2020 4 Chicago 7726.23
... ... ... ..
2021 1 Amesterdão 7261.28
2021 1 Berlim 3648.28
2021 1 Chicago 1027.27
... ... ... ..

Junta-se em um esquema de flocos de neve

Ao usar um esquema de flocos de neve, as dimensões podem ser parcialmente normalizadas; exigindo várias junções para relacionar tabelas de fatos com dimensões de flocos de neve. Por exemplo, suponha que seu data warehouse inclua uma tabela de dimensões DimProduct a partir da qual as categorias de produtos foram normalizadas em uma tabela DimCategory separada. Uma consulta para agregar itens vendidos por categoria de produto pode ser semelhante ao exemplo a seguir:

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;

Os resultados desta consulta incluem o número de itens vendidos para cada categoria de produto:

ProductCategory ItensVendidos
Accessories 28271
Bits e pedaços 5368
... ...

Nota

As cláusulas JOIN para FactSales e DimProduct e para DimProduct e DimCategory são necessárias, mesmo que nenhum campo de DimProduct seja retornado pela consulta.

Usando funções de classificação

Outro tipo comum de consulta analítica é particionar os resultados com base em um atributo de dimensão e classificar os resultados dentro de cada partição. Por exemplo, você pode querer classificar as lojas a cada ano pela receita de vendas. Para atingir essa meta, você pode usar funções de classificação Transact-SQL, como ROW_NUMBER, RANK, DENSE_RANKe NTILE. Essas funções permitem que você particione os dados em categorias, cada uma retornando um valor específico que indica a posição relativa de cada linha dentro da partição:

  • ROW_NUMBER retorna a posição ordinal da linha dentro da partição. Por exemplo, a primeira linha é numerada como 1, a segunda 2 e assim por diante.
  • RANK retorna a posição classificada de cada linha nos resultados ordenados. Por exemplo, em uma partição de lojas ordenadas por volume de vendas, a loja com o maior volume de vendas é classificada como 1. Se várias lojas tiverem os mesmos volumes de vendas, elas serão classificadas da mesma forma, e a classificação atribuída às lojas subsequentes reflete o número de lojas que têm volumes de vendas mais altos - incluindo empates.
  • DENSE_RANK classifica linhas em uma partição da mesma forma que RANK, mas quando várias linhas têm a mesma classificação, as linhas subsequentes são posições de classificação ignoram empates.
  • NTILE retorna o percentil especificado no qual a linha cai. Por exemplo, em uma partição de lojas ordenadas por volume de vendas, NTILE(4) retorna o quartil em que o volume de vendas de uma loja o coloca.

Por exemplo, considere a consulta seguinte:

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;

A consulta divide os produtos em agrupamentos com base em suas categorias e, dentro de cada partição de categoria, a posição relativa de cada produto é determinada com base em seu preço de tabela. Os resultados dessa consulta podem ser semelhantes à tabela a seguir:

ProductCategory ProductName PreçoListado Número da linha Posição DenseRank Quartil
Accessories Widget 8.99 1 1 1 1
Accessories Knicknak 8.49 2 2 2 1
Accessories Roda dentada 5,99 3 3 3 2
Accessories Doodah 5,99 4 3 3 2
Accessories Emaranhado 2.99 5 5 4 3
Accessories Badabing 0.25 6 6 5 4
Bits e pedaços Flimflam 7.49 1 1 1 1
Bits e pedaços Snickity wotsit 6.99 2 2 2 1
Bits e pedaços Flange 4.25 3 3 3 2
... ... ... ... ... ... ...

Nota

Os resultados da amostra demonstram a diferença entre RANK e DENSE_RANK. Note-se que na categoria Acessórios , os produtos Sprocket e Doodah têm o mesmo preço de tabela, e ambos estão classificados como o 3º produto mais caro. O próximo produto com preço mais alto tem um RANK de 5 (há quatro produtos mais caros do que ele) e um DENSE_RANK de 4 (há três preços mais altos).

Para saber mais sobre funções de classificação, consulte Funções de classificação (Transact-SQL) na documentação do Azure Synapse Analytics.

Recuperando uma contagem aproximada

Embora o objetivo de um armazém de dados seja principalmente dar suporte a modelos de dados analíticos e relatórios para a empresa; Analistas de dados e cientistas de dados geralmente precisam realizar alguma exploração inicial de dados, apenas para determinar a escala básica e a distribuição dos dados.

Por exemplo, a consulta a seguir usa a COUNT função para recuperar o número de vendas para cada ano em um data warehouse hipotético:

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;

Os resultados dessa consulta podem ser semelhantes à tabela a seguir:

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

O volume de dados em um data warehouse pode significar que até mesmo consultas simples para contar o número de registros que atendem aos critérios especificados podem levar um tempo considerável para serem executadas. Em muitos casos, uma contagem precisa não é necessária - uma estimativa aproximada será suficiente. Nesses casos, você pode usar a APPROX_COUNT_DISTINCT função como mostrado no exemplo a seguir:

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;

A APPROX_COUNT_DISTINCT função usa um algoritmo HyperLogLog para recuperar uma contagem aproximada. É garantido que o resultado tenha uma taxa de erro máxima de 2% com 97% de probabilidade, de modo que os resultados desta consulta com os mesmos dados hipotéticos de antes podem ser semelhantes à tabela a seguir:

CalendarYear Aprox. Encomendas
2019 235552
2020 290436
2021 304633
... ...

As contagens são menos precisas, mas ainda assim suficientes para uma comparação aproximada das vendas anuais. Com um grande volume de dados, a consulta usando a função é concluída mais rapidamente, e a precisão reduzida pode ser uma compensação aceitável durante a APPROX_COUNT_DISTINCT exploração de dados básicos.

Nota

Consulte a documentação da função APPROX_COUNT_DISTINCT para obter mais detalhes.