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



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow