Servidor SQL:Diferencia entre PARTICIÓN POR y GRUPO POR
-
18-09-2019 - |
Pregunta
he estado usando GROUP BY
para todo tipo de consultas agregadas a lo largo de los años.Recientemente, he estado aplicando ingeniería inversa a un código que utiliza PARTITION BY
para realizar agregaciones.Al leer toda la documentación que puedo encontrar sobre PARTITION BY
, suena mucho a GROUP BY
, ¿tal vez con una pequeña funcionalidad adicional agregada?¿Son dos versiones de la misma funcionalidad general o son algo completamente diferente?
Solución
Se utilizan en diferentes lugares. group by
modifica toda la consulta, como:
select customerId, count(*) as orderCount
from Orders
group by customerId
Pero partition by
solo funciona en una función de ventana , como row_number
:
select row_number() over (partition by customerId order by orderId)
as OrderNumberForThisCustomer
from Orders
A group by
reduce normalmente el número de filas devueltas por rodar hacia arriba y calcular los promedios o sumas para cada fila. partition by
no afecta al número de filas devueltas, pero cambia la forma de calcular el resultado de una función de ventana.
Otros consejos
Podemos poner un ejemplo sencillo.
Considere una tabla llamada TableA
con los siguientes 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
El grupo de SQL BY se puede utilizar en una instrucción SELECT para recoger datos a través de varios registros y el grupo de los resultados por uno o más columnas.
En más sencilla GRUPO palabras de instrucción se utiliza en conjunción con las funciones de agregado para agrupar el conjunto de resultados por uno o más columnas.
Sintaxis:
SELECT expression1, expression2, ... expression_n,
aggregate_function (aggregate_expression)
FROM tables
WHERE conditions
GROUP BY expression1, expression2, ... expression_n;
Podemos aplicar GROUP BY
en nuestra mesa:
select SUM(Mark)marksum,firstname from TableA
group by id,firstName
Resultados:
marksum firstname
----------------
94 ann
134 arun
47 new
41 sruthy
En nuestra mesa real que tenemos 7 filas y cuando aplicamos GROUP BY id
, el grupo de servidores basado en los resultados id
:
En palabras sencillas:
aquí
GROUP BY
normalmente reduce el número de filas devueltas por laminado para arriba y calcularSum()
para cada fila.
PARTITION BY
Antes de ir a la partición, echemos un vistazo a la cláusula OVER
:
De acuerdo con la definición de MSDN:
OVER cláusula define una ventana o especificado por el usuario conjunto de filas dentro de una resultados de la consulta. Una función de ventana calcula entonces un valor para cada fila en la ventana. Puede utilizar la cláusula OVER con funciones para calcular valores agregados tales como medias móviles, agregados acumulados, totales acumulados, o una N superior por los resultados del grupo.
por partición no reducir el número de filas devueltas.
Podemos aplicar PARTITION BY en nuestra tabla de ejemplo:
SELECT SUM(Mark) OVER (PARTITION BY id) AS marksum, firstname FROM TableA
Resultados:
marksum firstname
-------------------
134 arun
134 arun
134 arun
94 ann
94 ann
41 sruthy
47 new
Mira los resultados - se repartirá las filas y vuelve todos filas, a diferencia de GROUP BY
. partition by
en realidad no enrollar los datos. Se le permite restablecer algo en función de cada grupo. Por ejemplo, se puede obtener un ordinal de columna dentro de un grupo mediante la partición en el campo de agrupamiento y usando rownum()
sobre las filas de ese grupo. Esto le da algo que se comporta un poco como una columna de identidad que restablece al comienzo de cada grupo.
PARTITION BY Divide el conjunto de resultados en particiones. La función de ventana se aplica a cada partición por separado y se reinicia de cálculo para cada partición.
Encontrados en este enlace: OVER Cláusula
Proporciona datos acumulados sin necesidad de acumularlos.
es decir.Supongamos que quiero devolver la posición relativa de la región de ventas.
Usando PARTITION BY, puedo devolver el monto de las ventas para una región determinada y el importe MÁXIMO en todas las regiones de ventas en la misma fila.
Esto significa que tendrá datos repetidos, pero puede ser adecuado para el consumidor final en el sentido de que los datos se han agregado pero no se han perdido, como sería el caso con GROUP BY.
PARTITION BY
es analítico, mientras que GROUP BY
es agregado. Para utilizar PARTITION BY
, hay que contenerlo con un SOBRE cláusula .
A partir de mi entendimiento partición es casi idéntico al Grupo A, pero con las siguientes diferencias:
Ese grupo de realidad grupos el conjunto de resultados que regresan una fila por cada grupo, que por lo tanto resulta en SQL Server sólo permite en las funciones de agregado lista de selección o columnas que forman parte del grupo por la cláusula (en cuyo caso, SQL Server puede garantizar que hay resultados únicos para cada grupo).
Considere por ejemplo MySQL que permite tener en las columnas de lista de selección que no están definidos en la cláusula GROUP BY, en cuyo caso aún se devuelve una fila por cada grupo, sin embargo si la columna no tiene resultados únicos entonces hay hay garantía de lo que será la salida!
Pero con partición, aunque los resultados de la función son idénticos a los resultados de una función agregada con Agrupar por, todavía está recibiendo el conjunto de resultados normal, lo que significa que uno está recibiendo una fila por fila subyacente, y no una fila por cada grupo, y debido a esto uno puede tener columnas que no son únicos por grupo en la lista SELECT.
Así como un resumen, Grupo Por sería mejor cuando se necesita una salida de una fila por cada grupo, y la partición sería mejor cuando uno tiene todas las filas, pero todavía quiere que la función de agregado basado en un grupo.
Por supuesto, también puede haber problemas de rendimiento, consulte http://social.msdn.microsoft.com/Forums/ms-MY/transactsql/thread/0b20c2b5-1607-40bc-b7a7-0c60a2a55fba .
Supongamos que tenemos 14 registros de la columna name
en la tabla
en group by
select name,count(*) as totalcount from person where name='Please fill out' group BY name;
se dará cuenta de en una sola fila es decir 14
pero en partition by
select row_number() over (partition by name) as total from person where name = 'Please fill out';
lo hará 14 filas de aumento en el recuento
Pequeño observación. mecanismo de automatización para generar dinámicamente SQL utilizando la 'partición' es mucho más sencillo de implementar en relación con el 'grupo por'. En el caso del 'grupo por', hay que cuidar el contenido de la columna 'Seleccionar'.
Lo siento por mi Inglés.
Tiene muy diferentes escenarios de uso. Cuando se utiliza GROUP BY que fusionar algunos de los registros de las columnas que son iguales y que tiene una agregación del conjunto de resultados.
Sin embargo, cuando se utiliza PARTITION BY su resultado es el mismo, pero sólo hay una agregación sobre las funciones de la ventana y no se combinan los registros, todavía tendrá el mismo número de registros.
Aquí es un artículo útil rally de explicar la diferencia: 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