Microsoft SQL Server
AGRUPAR POR
Buscar..
Agrupación simple
Tabla de Pedidos
Identificación del cliente | Identificación de producto | Cantidad | Precio |
---|---|---|---|
1 | 2 | 5 | 100 |
1 | 3 | 2 | 200 |
1 | 4 | 1 | 500 |
2 | 1 | 4 | 50 |
3 | 5 | 6 | 700 |
Al agrupar por una columna específica, solo se devuelven los valores únicos de esta columna.
SELECT customerId
FROM orders
GROUP BY customerId;
Valor de retorno:
Identificación del cliente |
---|
1 |
2 |
3 |
Las funciones agregadas como count()
aplican a cada grupo y no a la tabla completa:
SELECT customerId,
COUNT(productId) as numberOfProducts,
sum(price) as totalPrice
FROM orders
GROUP BY customerId;
Valor de retorno:
Identificación del cliente | número de productos | precio total |
---|---|---|
1 | 3 | 800 |
2 | 1 | 50 |
3 | 1 | 700 |
GRUPO POR VARIAS COLECCIONES
Uno podría querer agrupar por más de una columna
declare @temp table(age int, name varchar(15))
insert into @temp
select 18, 'matt' union all
select 21, 'matt' union all
select 21, 'matt' union all
select 18, 'luke' union all
select 18, 'luke' union all
select 21, 'luke' union all
select 18, 'luke' union all
select 21, 'luke'
SELECT Age, Name, count(1) count
FROM @temp
GROUP BY Age, Name
Agrupará por edad y nombre y producirá:
Años | Nombre | contar |
---|---|---|
18 | luke | 3 |
21 | luke | 2 |
18 | mate | 1 |
21 | mate | 2 |
Agrupar por con múltiples tablas, múltiples columnas.
Agrupar por se utiliza a menudo con la instrucción de unión. Supongamos que tenemos dos tablas. La primera es la tabla de alumnos:
Carné de identidad | Nombre completo | Años |
---|---|---|
1 | Matt Jones | 20 |
2 | Frank blue | 21 |
3 | Anthony Angel | 18 |
La segunda mesa es la tabla de materias que cada estudiante puede tomar:
Subject_Id | Tema |
---|---|
1 | Matemáticas |
2 | EDUCACIÓN FÍSICA |
3 | Física |
Y debido a que un estudiante puede asistir a muchas asignaturas y a una sola materia pueden asistir muchos (de ahí la relación N: N), necesitamos tener una tercera tabla de "límites". Llamemos a la tabla Students_subjects:
Subject_Id | Identificación del Estudiante |
---|---|
1 | 1 |
2 | 2 |
2 | 1 |
3 | 2 |
1 | 3 |
1 | 1 |
Ahora digamos que queremos saber la cantidad de asignaturas a las que asiste cada estudiante. En este caso, la instrucción GROUP BY
independiente no es suficiente, ya que la información no está disponible a través de una sola tabla. Por lo tanto, necesitamos usar GROUP BY
con la instrucción JOIN
:
Select Students.FullName, COUNT(Subject Id) as SubjectNumber FROM Students_Subjects
LEFT JOIN Students
ON Students_Subjects.Student_id = Students.Id
GROUP BY Students.FullName
El resultado de la consulta dada es el siguiente:
Nombre completo | SubjectNumber |
---|---|
Matt Jones | 3 |
Frank blue | 2 |
Anthony Angel | 1 |
Para un ejemplo aún más complejo de uso de GROUP BY, digamos que el estudiante podría asignar el mismo tema a su nombre más de una vez (como se muestra en la tabla Students_Subjects). En este escenario, podríamos contar el número de veces que cada materia fue asignada a un estudiante agrupando por más de una columna:
SELECT Students.FullName, Subjects.Subject,
COUNT(Students_subjects.Subject_id) AS NumberOfOrders
FROM ((Students_Subjects
INNER JOIN Students
ON Students_Subjcets.Student_id=Students.Id)
INNER JOIN Subjects
ON Students_Subjects.Subject_id=Subjects.Subject_id)
GROUP BY Fullname,Subject
Esta consulta da el siguiente resultado:
Nombre completo | Tema | SubjectNumber |
---|---|---|
Matt Jones | Matemáticas | 2 |
Matt Jones | EDUCACIÓN FÍSICA | 1 |
Frank blue | EDUCACIÓN FÍSICA | 1 |
Frank blue | Física | 1 |
Anthony Angel | Matemáticas | 1 |
TENIENDO
Debido a que la cláusula WHERE
se evalúa antes de GROUP BY
, no puede usar WHERE
para reducir los resultados de la agrupación (generalmente una función agregada, como COUNT(*)
). Para satisfacer esta necesidad, se puede utilizar la cláusula HAVING
.
Por ejemplo, utilizando los siguientes datos:
DECLARE @orders TABLE(OrderID INT, Name NVARCHAR(100))
INSERT INTO @orders VALUES
( 1, 'Matt' ),
( 2, 'John' ),
( 3, 'Matt' ),
( 4, 'Luke' ),
( 5, 'John' ),
( 6, 'Luke' ),
( 7, 'John' ),
( 8, 'John' ),
( 9, 'Luke' ),
( 10, 'John' ),
( 11, 'Luke' )
Si deseamos obtener el número de pedidos que ha realizado cada persona, utilizaríamos
SELECT Name, COUNT(*) AS 'Orders'
FROM @orders
GROUP BY Name
y obten
Nombre | Pedidos |
---|---|
Mate | 2 |
Juan | 5 |
Lucas | 4 |
Sin embargo, si queremos limitar esto a las personas que han realizado más de dos órdenes, podemos agregar una cláusula HAVING
.
SELECT Name, COUNT(*) AS 'Orders'
FROM @orders
GROUP BY Name
HAVING COUNT(*) > 2
rendirá
Nombre | Pedidos |
---|---|
Juan | 5 |
Lucas | 4 |
Tenga en cuenta que, al igual que GROUP BY
, las columnas que se colocan en HAVING
deben coincidir exactamente con sus contrapartes en la instrucción SELECT
. Si en el ejemplo anterior hubiéramos dicho en su lugar
SELECT Name, COUNT(DISTINCT OrderID)
Nuestra cláusula HAVING
tendría que decir
HAVING COUNT(DISTINCT OrderID) > 2
GROUP BY con ROLLUP y CUBE
El operador ROLLUP es útil para generar informes que contienen subtotales y totales.
CUBE genera un conjunto de resultados que muestra agregados para todas las combinaciones de valores en las columnas seleccionadas.
ROLLUP genera un conjunto de resultados que muestra agregados para una jerarquía de valores en las columnas seleccionadas.
ít Color Cantidad Mesa Azul 124 Mesa rojo 223 Silla Azul 101 Silla rojo 210
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
ELSE ISNULL(Item, 'UNKNOWN')
END AS Item,
CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
ELSE ISNULL(Color, 'UNKNOWN')
END AS Color,
SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH ROLLUP
Item Color QtySum
-------------------- -------------------- --------------------------
Chair Blue 101.00
Chair Red 210.00
Chair ALL 311.00
Table Blue 124.00
Table Red 223.00
Table ALL 347.00
ALL ALL 658.00
(7 fila (s) afectadas)
Si la palabra clave ROLLUP en la consulta se cambia a CUBE, el conjunto de resultados de CUBE es el mismo, excepto que estas dos filas adicionales se devuelven al final:
ALL Blue 225.00
ALL Red 433.00
https://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx