Neste artigo, vamos explorar quando e como usar a cláusula SQL PARTITION BY e compará-la ao uso da cláusula GROUP BY.
Compreendendo a função Janela
Os usuários de banco de dados usam funções agregadas como MAX(), MIN(), AVERAGE() e COUNT() para realizar a análise de dados. Essas funções operam em uma tabela inteira e retornam dados agregados únicos usando a cláusula GROUP BY. Às vezes, exigimos valores agregados em um pequeno conjunto de linhas. Nesse caso, a função Window combinada com a função agregada ajuda a obter a saída desejada. A função Window usa a cláusula OVER() e pode incluir as seguintes funções:
- Particionar por: Isso divide as linhas ou o conjunto de resultados da consulta em pequenas partições.
- Ordenar por: Isso organiza as linhas em ordem crescente ou decrescente para a janela de partição. A ordem padrão é crescente.
- Linha ou intervalo: Você pode limitar ainda mais as linhas em uma partição especificando o início e os pontos de extremidade.
Neste artigo, vamos nos concentrar em explorar a cláusula SQL PARTITION BY.
Preparando dados de amostra
Suponha que tenhamos uma tabela [SalesLT].[Orders] que armazena os detalhes do pedido do cliente. Possui uma coluna [Cidade] que especifica a cidade do cliente de onde o pedido foi feito.
CREATE TABLE [SalesLT].[Orders] ( orderid INT, orderdate DATE, customerName VARCHAR(100), City VARCHAR(50), amount MONEY ) INSERT INTO [SalesLT].[Orders] SELECT 1,'01/01/2021','Mohan Gupta','Alwar',10000 UNION ALL SELECT 2,'02/04/2021','Lucky Ali','Kota',20000 UNION ALL SELECT 3,'03/02/2021','Raj Kumar','Jaipur',5000 UNION ALL SELECT 4,'04/02/2021','Jyoti Kumari','Jaipur',15000 UNION ALL SELECT 5,'05/03/2021','Rahul Gupta','Jaipur',7000 UNION ALL SELECT 6,'06/04/2021','Mohan Kumar','Alwar',25000 UNION ALL SELECT 7,'07/02/2021','Kashish Agarwal','Alwar',15000 UNION ALL SELECT 8,'08/03/2021','Nagar Singh','Kota',2000 UNION ALL SELECT 9,'09/04/2021','Anil KG','Alwar',1000 Go
Digamos que queremos saber o valor total dos pedidos por local (Cidade). Para isso, usamos a função SUM() e GROUP BY conforme mostrado abaixo.
SELECT City AS CustomerCity ,sum(amount) AS totalamount FROM [SalesLT].[Orders] GROUP BY city ORDER BY city
No conjunto de resultados, não podemos usar as colunas não agregadas na instrução SELECT. Por exemplo, não podemos exibir [CustomerName] na saída porque não está incluído na cláusula GROUP BY.
O SQL Server fornece a seguinte mensagem de erro se você tentar usar a coluna não agregada na lista de colunas.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount FROM [SalesLT].[Orders]
Conforme mostrado abaixo, a cláusula PARTITION BY cria uma janela menor (conjunto de linhas de dados), realiza a agregação e a exibe. Você também pode visualizar colunas não agregadas nesta saída.
Da mesma forma, você pode usar as funções AVG(), MIN(), MAX() para calcular o valor médio, mínimo e máximo das linhas em uma janela.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount, Avg(amount) OVER(PARTITION BY city) AvgOrderAmount, Min(amount) OVER(PARTITION BY city) MinOrderAmount, MAX(amount) OVER(PARTITION BY city) MaxOrderAmount FROM [SalesLT].[Orders]
Usando a cláusula SQL PARTITION BY com a função ROW_NUMBER()
Anteriormente, obtínhamos os valores agregados em uma janela usando a cláusula PARTITION BY. Suponha que, em vez do total, exijamos o total cumulativo em uma partição.
Um total cumulativo funciona das seguintes maneiras.
Linha | Total acumulado |
1 | Classificação 1+ 2 |
2 | Classificação 2+3 |
3 | Classificação 3+4 |
A classificação da linha é calculada usando a função ROW_NUMBER(). Vamos primeiro usar esta função e ver as fileiras das linhas.
- A função ROW_NUMBER() usa a cláusula OVER e PARTITION BY e classifica os resultados em ordem crescente ou decrescente. Ele começa a classificar as linhas de 1 por ordem de classificação.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number] FROM [SalesLT].[Orders]
Por exemplo, na cidade [Alwar], a linha com o valor mais alto (25.000,00) está na linha 1. Conforme mostrado abaixo, ela classifica as linhas na janela especificada pela cláusula PARTITION BY. Por exemplo, temos três cidades diferentes [Alwar], [Jaipur] e [Kota], e cada janela (cidade) recebe suas fileiras de linhas.
Para calcular o total acumulado, usamos os seguintes argumentos.
- CURRENT ROW:especifica o ponto inicial e final no intervalo especificado.
- 1 seguinte:especifica o número de linhas (1) a seguir da linha atual.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS CumulativeSUM FROM [SalesLT].[Orders]
A imagem a seguir mostra que você obtém um total cumulativo em vez de um total geral em uma janela especificada pela cláusula PARTITION BY.
Se usarmos ROWS UNBOUNDED PRECEDING na cláusula SQL PARTITION BY, ele calcula o total acumulado da seguinte maneira. Ele usa as linhas atuais junto com as linhas com os valores mais altos na janela especificada.
Linha | Total acumulado |
1 | Classificação 1 |
2 | Classificação 1+2 |
3 | Classificação 1+2+3 |
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS UNBOUNDED PRECEDING) AS CumulativeSUM FROM [SalesLT].[Orders]
Comparando a cláusula GROUP BY e SQL PARTITION BY
GRUPAR POR | PARTIÇÃO POR |
Ele retorna uma linha por grupo após calcular os valores agregados. | Ele retorna todas as linhas da instrução SELECT junto com colunas adicionais de valores agregados. |
Não podemos usar a coluna não agregada na instrução SELECT. | Podemos usar colunas obrigatórias na instrução SELECT e isso não produz erros para a coluna não agregada. |
Requer o uso da cláusula HAVING para filtrar registros da instrução SELECT. | A função PARTITION pode ter predicados adicionais na cláusula WHERE além das colunas usadas na instrução SELECT. |
O GROUP BY é usado em agregados regulares. | PARTITION BY é usado em agregados em janela. |
Não podemos usá-lo para calcular números de linha ou suas classificações. | Ele pode calcular números de linha e suas classificações na janela menor. |
Colocando em uso
É recomendável usar a cláusula SQL PARTITION BY ao trabalhar com vários grupos de dados para os valores agregados no grupo individual. Da mesma forma, pode ser usado para visualizar as linhas originais com a coluna adicional de valores agregados.