Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Se aplica a:SQL Server
Azure SQL Database
Instancia
administrada de Azure SQLBase de datos SQL en Microsoft Fabric
GROUPING_ID Es una función que calcula el nivel de agrupación.
GROUPING_ID solo se puede usar en las SELECT <select> cláusulas list, HAVING, o ORDER BY cuando GROUP BY se especifica .
Convenciones de sintaxis de Transact-SQL
Sintaxis
GROUPING_ID ( <column_expression> [ , ...n ] )
Argumentos
<column_expression>
Un column_expression en una cláusula SELECT - GROUP BY.
Tipos de valores devueltos
int
Comentarios
GROUPING_ID <column_expression> debe coincidir exactamente con la expresión de la GROUP BY lista. Por ejemplo, si va a agrupar por DATEPART (yyyy, <column name>), use GROUPING_ID (DATEPART (yyyy, <column name>)); o si va a agrupar por <column name>, use GROUPING_ID (<column name>).
Comparar GROUPING_ID() con GROUPING()
GROUPING_ID (<column_expression> [ , ...n ]) introduce el equivalente de la GROUPING (<column_expression>) devolución para cada columna de su lista de columnas en cada fila de salida, como una cadena de uno y ceros.
GROUPING_ID interpreta esa cadena como un número base-2 y devuelve el entero equivalente.
Por ejemplo, considere la siguiente instrucción:
SELECT a, b, c, SUM(d),
GROUPING_ID(a, b, c)
FROM T
GROUP BY <group_by_list>
En esta tabla se muestran los GROUPING_ID() valores de entrada y salida.
| Columnas agregadas | Entrada de GROUPING_ID (a, b, c) = GROUPING(a) + GROUPING(b) + GROUPING(c) | salida de GROUPING_ID() |
|---|---|---|
a |
100 |
4 |
b |
010 |
2 |
c |
001 |
1 |
ab |
110 |
6 |
ac |
101 |
5 |
bc |
011 |
3 |
abc |
111 |
7 |
Definición técnica de GROUPING_ID()
Cada GROUPING_ID argumento debe ser un elemento de la GROUP BY lista.
GROUPING_ID()devuelve un mapa de bits entero cuyos bits n más bajos se pueden iluminar. Un bit iluminado indica que el argumento correspondiente no es una columna de agrupación para la fila de salida especificada. El bit de orden más bajo corresponde al argumento n y el bit de orden inferior n-1 corresponde al argumento 1.
equivalentes de GROUPING_ID()
Para una sola consulta de agrupación, GROUPING (<column_expression>) es equivalente a GROUPING_ID (<column_expression>)y devuelven 0.
Por ejemplo, las siguientes instrucciones son equivalentes:
Instrucción A
SELECT GROUPING_ID(A, B)
FROM T
GROUP BY CUBE(A, B)
Instrucción B
SELECT 3 FROM T GROUP BY ()
UNION ALL
SELECT 1 FROM T GROUP BY A
UNION ALL
SELECT 2 FROM T GROUP BY B
UNION ALL
SELECT 0 FROM T GROUP BY A, B
Ejemplos
Los ejemplos de código de este artículo usan la base de datos de ejemplo de AdventureWorks2025 o AdventureWorksDW2025, que puede descargar de la página principal de Ejemplos de Microsoft SQL Server y proyectos de comunidad.
A Uso de GROUPING_ID para identificar niveles de agrupación
En el ejemplo siguiente se devuelve el recuento de empleados por Name y Title, y el total de la empresa en la AdventureWorks2025 base de datos.
GROUPING_ID() se usa para crear un valor en cada fila de la columna Title que identifica su nivel de agregación.
SELECT D.Name,
CASE
WHEN GROUPING_ID(D.Name, E.JobTitle) = 0 THEN E.JobTitle
WHEN GROUPING_ID(D.Name, E.JobTitle) = 1 THEN N'Total: ' + D.Name
WHEN GROUPING_ID(D.Name, E.JobTitle) = 3 THEN N'Company Total:'
ELSE N'Unknown'
END AS N'Job Title',
COUNT(E.BusinessEntityID) AS N'Employee Count'
FROM HumanResources.Employee E
INNER JOIN HumanResources.EmployeeDepartmentHistory DH
ON E.BusinessEntityID = DH.BusinessEntityID
INNER JOIN HumanResources.Department D
ON D.DepartmentID = DH.DepartmentID
WHERE DH.EndDate IS NULL
AND D.DepartmentID IN (12, 14)
GROUP BY ROLLUP(D.Name, E.JobTitle);
B. Uso de GROUPING_ID para filtrar un conjunto de resultados
Ejemplo básico
En el código siguiente, para devolver solo las filas que tienen un recuento de empleados por título, quite los caracteres de comentario de HAVING GROUPING_ID(D.Name, E.JobTitle) = 0;. Para devolver solo las filas que tienen un recuento de empleados por departamento, quite los caracteres de comentario de HAVING GROUPING_ID(D.Name, E.JobTitle) = 1;.
SELECT D.Name,
E.JobTitle,
GROUPING_ID(D.Name, E.JobTitle) AS [Grouping Level],
COUNT(E.BusinessEntityID) AS [Employee Count]
FROM HumanResources.Employee AS E
INNER JOIN HumanResources.EmployeeDepartmentHistory AS DH
ON E.BusinessEntityID = DH.BusinessEntityID
INNER JOIN HumanResources.Department AS D
ON D.DepartmentID = DH.DepartmentID
WHERE DH.EndDate IS NULL
AND D.DepartmentID IN (12, 14)
GROUP BY ROLLUP(D.Name, E.JobTitle)
-- HAVING GROUPING_ID(D.Name, E.JobTitle) = 0; -- All titles
-- HAVING GROUPING_ID(D.Name, E.JobTitle) = 1; -- Group by Name;
Este es el conjunto de resultados sin filtrar.
| Nombre | Título | Nivel de agrupación | Número de empleados | Nombre |
|---|---|---|---|---|
| Control de Documentos | Especialista en control | 0 | 2 | Control de Documentos |
| Control de Documentos | Asistente de Control de Documentos | 0 | 2 | Control de Documentos |
| Control de Documentos | Gestor de Control de Documentos | 0 | 1 | Control de Documentos |
| Control de Documentos | NULL |
1 | 5 | Control de Documentos |
| Instalaciones y mantenimiento | Asistente Administrativo de Instalaciones | 0 | 1 | Instalaciones y mantenimiento |
| Instalaciones y mantenimiento | Responsable de Instalaciones | 0 | 1 | Instalaciones y mantenimiento |
| Instalaciones y mantenimiento | Janitor | 0 | 4 | Instalaciones y mantenimiento |
| Instalaciones y mantenimiento | Supervisor de Mantenimiento | 0 | 1 | Instalaciones y mantenimiento |
| Instalaciones y mantenimiento | NULL |
1 | 7 | Instalaciones y mantenimiento |
NULL |
NULL |
3 | 12 | NULL |
Ejemplo complejo
En el ejemplo siguiente se usa GROUPING_ID() para filtrar un conjunto de resultados que contiene varios niveles de agrupación por nivel de agrupación. Se puede usar código similar para crear una vista que tenga varios niveles de agrupación y un procedimiento almacenado que llame a la vista pasando un parámetro que filtre la vista por nivel de agrupación.
DECLARE @Grouping NVARCHAR(50);
DECLARE @GroupingLevel SMALLINT;
SET @Grouping = N'CountryRegionCode Total';
SELECT @GroupingLevel = (
CASE @Grouping
WHEN N'Grand Total' THEN 15
WHEN N'SalesPerson Total' THEN 14
WHEN N'Store Total' THEN 13
WHEN N'Store SalesPerson Total' THEN 12
WHEN N'CountryRegionCode Total' THEN 11
WHEN N'Group Total' THEN 7
ELSE N'Unknown'
END
);
SELECT T.[Group],
T.CountryRegionCode,
S.Name AS N'Store',
(
SELECT P.FirstName + ' ' + P.LastName
FROM Person.Person AS P
WHERE P.BusinessEntityID = H.SalesPersonID
) AS N'Sales Person',
SUM(TotalDue) AS N'TotalSold',
CAST(GROUPING(T.[Group]) AS CHAR(1)) + CAST(GROUPING(T.CountryRegionCode) AS CHAR(1)) + CAST(GROUPING(S.Name) AS CHAR(1)) + CAST(GROUPING(H.SalesPersonID) AS CHAR(1)) AS N'GROUPING base-2',
GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) AS N'GROUPING_ID',
CASE
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 15
THEN N'Grand Total'
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 14
THEN N'SalesPerson Total'
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 13
THEN N'Store Total'
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 12
THEN N'Store SalesPerson Total'
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 11
THEN N'CountryRegionCode Total'
WHEN GROUPING_ID((T.[Group]), (T.CountryRegionCode), (S.Name), (H.SalesPersonID)) = 7
THEN N'Group Total'
ELSE N'Error'
END AS N'Level'
FROM Sales.Customer AS C
INNER JOIN Sales.Store AS S
ON C.StoreID = S.BusinessEntityID
INNER JOIN Sales.SalesTerritory AS T
ON C.TerritoryID = T.TerritoryID
INNER JOIN Sales.SalesOrderHeader AS H
ON C.CustomerID = H.CustomerID
GROUP BY GROUPING SETS(
(S.Name,H.SalesPersonID),
(H.SalesPersonID),
(S.Name),
(T.[Group]),
(T.CountryRegionCode),
()
)
HAVING GROUPING_ID(
(T.[Group]),
(T.CountryRegionCode),
(S.Name),
(H.SalesPersonID)
) = @GroupingLevel
ORDER BY
GROUPING_ID(S.Name, H.SalesPersonID),
GROUPING_ID(
(T.[Group]),
(T.CountryRegionCode),
(S.Name),
(H.SalesPersonID)
) ASC;
C. Uso de GROUPING_ID() con ROLLUP y CUBE para identificar los niveles de agrupación
El código de los ejemplos siguientes muestra cómo usar GROUPING() para calcular la Bit Vector(base-2) columna.
GROUPING_ID() se usa para calcular la columna Integer Equivalent correspondiente. El orden de columnas en la función GROUPING_ID() es el contrario del orden de las columnas que concatena la función GROUPING().
En estos ejemplos, GROUPING_ID() se usa para crear un valor para cada fila de la columna Grouping Level que identifica el nivel de agrupación. Los niveles de agrupación no siempre son una lista consecutiva de enteros que comienzan por 1 (0, 1, 2, ...n).
Nota:
GROUPING y GROUPING_ID se pueden usar en una HAVING cláusula para filtrar un conjunto de resultados.
Ejemplo de ROLLUP
En este ejemplo, todos los niveles de agrupación no aparecen como lo hacen en el ejemplo siguiente CUBE . Si se cambia el orden de las columnas de la ROLLUP lista, también se deben cambiar los valores de nivel de la Grouping Level columna.
SELECT DATEPART(yyyy, OrderDate) AS N'Year',
DATEPART(mm, OrderDate) AS N'Month',
DATEPART(dd, OrderDate) AS N'Day',
SUM(TotalDue) AS N'Total Due',
CAST(GROUPING(DATEPART(dd, OrderDate)) AS CHAR(1)) + CAST(GROUPING(DATEPART(mm, OrderDate)) AS CHAR(1)) + CAST(GROUPING(DATEPART(yyyy, OrderDate)) AS CHAR(1)) AS N'Bit Vector(base-2)',
GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) AS N'Integer Equivalent',
CASE
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 0
THEN N'Year Month Day'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 1
THEN N'Year Month'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 2
THEN N'not used'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 3
THEN N'Year'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 4
THEN N'not used'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 5
THEN N'not used'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 6
THEN N'not used'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 7
THEN N'Grand Total'
ELSE N'Error'
END AS N'Grouping Level'
FROM Sales.SalesOrderHeader
WHERE DATEPART(yyyy, OrderDate) IN (N'2007', N'2008')
AND DATEPART(mm, OrderDate) IN (1, 2)
AND DATEPART(dd, OrderDate) IN (1, 2)
GROUP BY ROLLUP(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate))
ORDER BY GROUPING_ID(DATEPART(mm, OrderDate), DATEPART(yyyy, OrderDate), DATEPART(dd, OrderDate)),
DATEPART(yyyy, OrderDate),
DATEPART(mm, OrderDate),
DATEPART(dd, OrderDate);
A continuación se muestra un conjunto parcial de resultados.
| Year | Mes | Día | Total de vencimiento | Vector de bits (base-2) | Equivalente entero | Nivel de agrupación |
|---|---|---|---|---|---|---|
| 2007 | 1 | 1 | 1497452,6066 | 000 | 0 | Año Día del Mes |
| 2007 | 1 | 2 | 21772,3494 | 000 | 0 | Año Día del Mes |
| 2007 | 2 | 1 | 2705653,5913 | 000 | 0 | Año Día del Mes |
| 2007 | 2 | 2 | 21684,4068 | 000 | 0 | Año Día del Mes |
| 2008 | 1 | 1 | 1908122,0967 | 000 | 0 | Año Día del Mes |
| 2008 | 1 | 2 | 46458,0691 | 000 | 0 | Año Día del Mes |
| 2008 | 2 | 1 | 3108771,9729 | 000 | 0 | Año Día del Mes |
| 2008 | 2 | 2 | 54598,5488 | 000 | 0 | Año Día del Mes |
| 2007 | 1 | NULL |
1519224,956 | 100 | 1 | Año Mes |
| 2007 | 2 | NULL |
2727337,9981 | 100 | 1 | Año Mes |
| 2008 | 1 | NULL |
1954580,1658 | 100 | 1 | Año Mes |
| 2008 | 2 | NULL |
3163370,5217 | 100 | 1 | Año Mes |
| 2007 | NULL |
NULL |
4246562,9541 | 110 | 3 | Year |
| 2008 | NULL |
NULL |
5117950,6875 | 110 | 3 | Year |
NULL |
NULL |
NULL |
9364513,6416 | 111 | 7 | Total general |
Ejemplo de CUBE
En este ejemplo, la función GROUPING_ID() se usa para crear un valor para cada fila de la columna Grouping Level que identifica el nivel de agrupación.
A diferencia de ROLLUP en el ejemplo anterior, CUBE genera todos los niveles de agrupación. Si se cambia el orden de las columnas de la CUBE lista, también se deben cambiar los valores de nivel de la Grouping Level columna.
SELECT DATEPART(yyyy, OrderDate) AS N'Year',
DATEPART(mm, OrderDate) AS N'Month',
DATEPART(dd, OrderDate) AS N'Day',
SUM(TotalDue) AS N'Total Due',
CAST(GROUPING(DATEPART(dd, OrderDate)) AS CHAR(1)) + CAST(GROUPING(DATEPART(mm, OrderDate)) AS CHAR(1)) + CAST(GROUPING(DATEPART(yyyy, OrderDate)) AS CHAR(1)) AS N'Bit Vector(base-2)',
GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) AS N'Integer Equivalent',
CASE
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 0
THEN N'Year Month Day'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 1
THEN N'Year Month'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 2
THEN N'Year Day'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 3
THEN N'Year'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 4
THEN N'Month Day'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 5
THEN N'Month'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 6
THEN N'Day'
WHEN GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)) = 7
THEN N'Grand Total'
ELSE N'Error'
END AS N'Grouping Level'
FROM Sales.SalesOrderHeader
WHERE DATEPART(yyyy, OrderDate) IN (N'2007', N'2008')
AND DATEPART(mm, OrderDate) IN (1, 2)
AND DATEPART(dd, OrderDate) IN (1, 2)
GROUP BY CUBE(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate))
ORDER BY GROUPING_ID(DATEPART(yyyy, OrderDate), DATEPART(mm, OrderDate), DATEPART(dd, OrderDate)),
DATEPART(yyyy, OrderDate),
DATEPART(mm, OrderDate),
DATEPART(dd, OrderDate);
A continuación se muestra un conjunto parcial de resultados.
| Year | Mes | Día | Total de vencimiento | Vector de bits (base-2) | Equivalente entero | Nivel de agrupación |
|---|---|---|---|---|---|---|
| 2007 | 1 | 1 | 1497452,6066 | 000 | 0 | Año Día del Mes |
| 2007 | 1 | 2 | 21772,3494 | 000 | 0 | Año Día del Mes |
| 2007 | 2 | 1 | 2705653,5913 | 000 | 0 | Año Día del Mes |
| 2007 | 2 | 2 | 21684,4068 | 000 | 0 | Año Día del Mes |
| 2008 | 1 | 1 | 1908122,0967 | 000 | 0 | Año Día del Mes |
| 2008 | 1 | 2 | 46458,0691 | 000 | 0 | Año Día del Mes |
| 2008 | 2 | 1 | 3108771,9729 | 000 | 0 | Año Día del Mes |
| 2008 | 2 | 2 | 54598,5488 | 000 | 0 | Año Día del Mes |
| 2007 | 1 | NULL |
1519224,956 | 100 | 1 | Año Mes |
| 2007 | 2 | NULL |
2727337,9981 | 100 | 1 | Año Mes |
| 2008 | 1 | NULL |
1954580,1658 | 100 | 1 | Año Mes |
| 2008 | 2 | NULL |
3163370,5217 | 100 | 1 | Año Mes |
| 2007 | NULL |
1 | 4203106,1979 | 010 | 2 | Día de Año |
| 2007 | NULL |
2 | 43456.7562 | 010 | 2 | Día de Año |
| 2008 | NULL |
1 | 5016894.0696 | 010 | 2 | Día de Año |
| 2008 | NULL |
2 | 101056.6179 | 010 | 2 | Día de Año |
| 2007 | NULL |
NULL |
4246562,9541 | 110 | 3 | Year |
| 2008 | NULL |
NULL |
5117950,6875 | 110 | 3 | Year |
NULL |
1 | 1 | 3405574.7033 | 001 | 4 | Día del Mes |
NULL |
1 | 2 | 68230.4185 | 001 | 4 | Día del Mes |
NULL |
2 | 1 | 5814425.5642 | 001 | 4 | Día del Mes |
NULL |
2 | 2 | 76282.9556 | 001 | 4 | Día del Mes |
NULL |
1 | NULL |
3473805.1218 | 101 | 5 | Mes |
NULL |
2 | NULL |
5890708.5198 | 101 | 5 | Mes |
NULL |
NULL |
1 | 9220000.2675 | 011 | 6 | Día |
NULL |
NULL |
2 | 144513.3741 | 011 | 6 | Día |
NULL |
NULL |
NULL |
9364513,6416 | 111 | 7 | Total general |