SQL Server: Diferença entre PARTITION BY e GROUP BY
-
18-09-2019 - |
Pergunta
Eu tenho usado GROUP BY
para todos os tipos de consultas agregadas ao longo dos anos. Recentemente, eu estive a engenharia reversa algum código que usos PARTITION BY
para executar agregações. Na leitura através de toda a documentação que pode encontrar sobre PARTITION BY
, soa muito como GROUP BY
, talvez com um pouco de funcionalidade extra adicionado? São duas versões da mesma funcionalidade geral, ou são algo completamente diferente?
Solução
Eles são usados ??em lugares diferentes. modifica group by
toda a consulta, como:
select customerId, count(*) as orderCount
from Orders
group by customerId
Mas partition by
apenas funciona em uma função de janela , como row_number
:
select row_number() over (partition by customerId order by orderId)
as OrderNumberForThisCustomer
from Orders
A group by
normalmente reduz o número de linhas retornadas rolando-los e calcular médias ou somas para cada linha. partition by
não afeta o número de linhas retornadas, mas muda como resultado de uma função de janela é calculada.
Outras dicas
Podemos tomar um exemplo simples.
Considere uma tabela chamada TableA
com os seguintes valores:
id firstname lastname Mark
-------------------------------------------------------------------
1 arun prasanth 40
2 ann antony 45
3 sruthy abc 41
6 new abc 47
1 arun prasanth 45
1 arun prasanth 49
2 ann antony 49
GROUP BY
A cláusula SQL GROUP BY pode ser utilizado em uma instrução SELECT para coletar dados através de múltiplas fichas e agrupando os resultados por um ou mais colunas.
Em GROUP palavras mais simples pela declaração é usado em conjunto com as funções de agregação para o grupo de resultado-definidos por um ou mais colunas.
Sintaxe:
SELECT expression1, expression2, ... expression_n,
aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;
Podemos aplicar GROUP BY
na nossa tabela:
select SUM(Mark)marksum,firstname from TableA
group by id,firstName
Resultado:
marksum firstname
----------------
94 ann
134 arun
47 new
41 sruthy
Em nossa mesa real que temos 7 linhas e quando aplicamos GROUP BY id
, o grupo de servidores os resultados com base em id
:
Em palavras simples:
aqui
GROUP BY
normalmente reduz o número de linhas retornado por rolamento -los e calcularSum()
para cada linha.
PARTITION BY
Antes de ir para POR PARTITION, vamos olhar para a cláusula OVER
:
De acordo com a definição MSDN:
cláusula OVER define uma janela ou especificado pelo usuário conjunto de linhas dentro de um consulta resultar set. A função de janela, em seguida, calcula um valor para cada linha na janela. Você pode usar a cláusula OVER com funções para computar valores agregados, como médias móveis, agregados cumulativos, executando totais, ou de uma parte superior de N por resultados do grupo.
PARTITION BY não vai reduzir o número de linhas retornadas.
Podemos aplicar PARTITION BY na nossa tabela de exemplo:
SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA
Resultado:
marksum firstname
-------------------
134 arun
134 arun
134 arun
94 ann
94 ann
41 sruthy
47 new
Olhe para os resultados -. Ele vai dividir as linhas e retorna todas linhas, ao contrário GROUP BY
partition by
na verdade não enrolar a dados. Ele permite-lhe repor algo em uma base por grupo. Por exemplo, você pode ter uma coluna ordinal dentro de um grupo de particionamento no campo de agrupamento e usando rownum()
sobre as linhas dentro desse grupo. Isto dá-lhe algo que se comporta um pouco como uma coluna de identidade que redefine no início de cada grupo.
Por PARTITION Divide o conjunto de resultados em partições. A função de janela é aplicada a cada partição separadamente e de cálculo é reiniciado para cada partição.
encontrado neste link: SOBRE Cláusula
Ele fornece dados enroladas sem enrolar
i. Suponha que eu queira retornar a posição relativa da região de vendas
Usando PARTITION BY, eu posso devolver o montante de vendas para uma determinada região e a quantidade MAX em todas as regiões de vendas na mesma linha.
Isso significa que você terá que repetir os dados, mas pode atender o consumidor final, no sentido de que os dados foram agregados mas nenhum dado foi perdido -. Como seria o caso com GROUP BY
PARTITION BY
é analítica, enquanto GROUP BY
é agregada. Para utilizar PARTITION BY
, você tem que contê-lo com um SOBRE cláusula .
A partir de minha partição compreensão por é quase idêntico ao Grupo por, mas com as seguintes diferenças:
Esse grupo por realmente grupos do conjunto de resultados retornar uma linha por grupo, o que resulta, portanto, em SQL Server permitindo apenas na lista SELECT funções agregadas ou colunas que fazem parte do grupo pela cláusula (caso em que o SQL Server pode garantir que existem resultados únicos para cada grupo).
Considere, por exemplo MySQL que permite ter nas colunas lista SELECT que não estão definidos na cláusula Group By, caso em que uma linha ainda está sendo devolvido por grupo, no entanto, se a coluna não tem resultados únicos, então não há garantia de que será a saída!
Mas com partição, embora os resultados da função são idênticos aos resultados de uma função agregada com Group By, ainda que você está recebendo o conjunto de resultados normal, o que significa que um está recebendo uma linha por linha subjacente, e não uma linha por grupo, e por isso pode-se ter colunas que não são únicas por grupo na lista SELECT.
Assim como um resumo, Group By seria melhor quando precisa de uma saída de uma linha por grupo e partição seria melhor quando se precisa de todas as linhas, mas ainda quer a função de agregação com base em um grupo.
É claro que também pode haver problemas de desempenho, consulte http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba .
Suponha que temos 14 registros de coluna name
na tabela
em group by
select name,count(*) as totalcount from person where name='Please fill out' group BY name;
Ele lhe dará contagem em única ou seja linha 14
mas em partition by
select row_number() over (partition by name) as total from person where name = 'Please fill out';
que vai de 14 fileiras de aumento na contagem
pequeno. mecanismo de automação para gerar dinamicamente SQL usando o 'partição' é muito mais simples de implementar em relação ao 'grupo por'. No caso do 'grupo por' Devemos cuidar do conteúdo da coluna 'selecionar'.
desculpe pelo meu Inglês.
Ele tem realmente diferentes cenários de uso. Quando você usa GROUP BY você mesclar alguns dos registros para as colunas que são mesmo e você tem uma agregação do conjunto de resultados.
No entanto, quando você usa PARTITION pelo seu conjunto de resultados é o mesmo, mas você só tem uma agregação sobre as funções da janela e você não mesclar os registros, você ainda terá a mesma contagem de registros.
Aqui está um comício útil artigo explicando a diferença: http://alevryustemov.com/sql/sql-partition-by/
-- BELOW IS A SAMPLE WHICH OUTLINES THE SIMPLE DIFFERENCES
-- READ IT AND THEN EXECUTE IT
-- THERE ARE THREE ROWS OF EACH COLOR INSERTED INTO THE TABLE
-- CREATE A database called testDB
-- use testDB
USE [TestDB]
GO
-- create Paints table
CREATE TABLE [dbo].[Paints](
[Color] [varchar](50) NULL,
[glossLevel] [varchar](50) NULL
) ON [PRIMARY]
GO
-- Populate Table
insert into paints (color, glossLevel)
select 'red', 'eggshell'
union
select 'red', 'glossy'
union
select 'red', 'flat'
union
select 'blue', 'eggshell'
union
select 'blue', 'glossy'
union
select 'blue', 'flat'
union
select 'orange', 'glossy'
union
select 'orange', 'flat'
union
select 'orange', 'eggshell'
union
select 'green', 'eggshell'
union
select 'green', 'glossy'
union
select 'green', 'flat'
union
select 'black', 'eggshell'
union
select 'black', 'glossy'
union
select 'black', 'flat'
union
select 'purple', 'eggshell'
union
select 'purple', 'glossy'
union
select 'purple', 'flat'
union
select 'salmon', 'eggshell'
union
select 'salmon', 'glossy'
union
select 'salmon', 'flat'
/* COMPARE 'GROUP BY' color to 'OVER (PARTITION BY Color)' */
-- GROUP BY Color
-- row quantity defined by group by
-- aggregate (count(*)) defined by group by
select count(*) from paints
group by color
-- OVER (PARTITION BY... Color
-- row quantity defined by main query
-- aggregate defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color)
from paints
/* COMPARE 'GROUP BY' color, glossLevel to 'OVER (PARTITION BY Color, GlossLevel)' */
-- GROUP BY Color, GlossLevel
-- row quantity defined by GROUP BY
-- aggregate (count(*)) defined by GROUP BY
select count(*) from paints
group by color, glossLevel
-- Partition by Color, GlossLevel
-- row quantity defined by main query
-- aggregate (count(*)) defined by OVER-PARTITION BY
select color
, glossLevel
, count(*) OVER (Partition by color, glossLevel)
from paints