Monday, 2 March 2015

Using GROUP BY with ROLLUP, CUBE, and GROUPING SETS

The ROLLUP, CUBE, and GROUPING SETS operators are extensions of the GROUP BY clause. The ROLLUP, CUBE, or GROUPING SETS operators can generate the same result set as when you use UNION ALL to combine single grouping queries; however, using one of the GROUP BY operators is usually more efficient.
The GROUPING SETS operator can generate the same result set as that generated by using a simple GROUP BY, ROLLUP, or CUBE operator. When all the groupings that are generated by using a full ROLLUP or CUBE operator are not required, you can use GROUPING SETS to specify only the groupings that you want. The GROUPING SETS list can contain duplicate groupings; and, when GROUPING SETS is used with ROLLUP and CUBE, it might generate duplicate groupings. Duplicate groupings are retained as they would be by using UNION ALL.
NoteNote
CUBE, ROLLUP and GROUPING SETS do not support the CHECKSUM_AGG function.

Multiple columns that are in inner parentheses in the GROUPING SETS list are treated as a single set. For example, in the clause GROUP BY GROUPING SETS ((Colum1, Column2), Column3, Column4), Column1 and Column2 are treated as one column. For an example of how to use GROUPING SETS with composite elements, see example H later in this topic.
When the GROUPING SETS list contains multiple sets in inner parentheses, separated by commas, the output of the sets are concatenated. The result set is the cross product or Cartesian product of the grouping sets. For an example of how to use GROUP BY with concatenated ROLLUP operations, see example D later in this topic.

Queries that use the ROLLUP and CUBE operators generate some of the same result sets and perform some of the same calculations as OLAP applications. The CUBE operator generates a result set that can be used for cross tabulation reports. A ROLLUP operation can calculate the equivalent of an OLAP dimension or hierarchy.
For example, given a time dimension with the levels or attributes year, month, and day; the following ROLLUP operation generates the following groupings.
OperationGroupings
ROLLUP (DATEPART(yyyy,OrderDate)
    ,DATEPART(mm,OrderDate)
    ,DATEPART(dd,OrderDate)) 
year, month, day
year, month
year
()
Given a location dimension with the levels region and city concatenated with the time-dimension levels year, month, and day, the following ROLLUP operation outputs the following groupings.
OperationGroupings
ROLLUP (region, city),
ROLLUP (DATEPART(yyyy,OrderDate)
    ,DATEPART(mm,OrderDate)
    ,DATEPART(dd,OrderDate))
region, city, year, month, day
region, city, year, month
region, city, year
region, city
region, year, month, day
region, year, month
region, year
region
year, month, day
year, month
year
()
A CUBE operation of the same levels from the location and time dimensions outputs the following groupings.
OperationGrouping
CUBE (region, city
    ,DATEPART(yyyy,OrderDate)
    ,DATEPART(mm,OrderDate)
    ,DATEPART(dd,OrderDate))
region, city, year, month, day
region, city, year, month
region, city, year
region, city
region, city, month, day
region, city, month
region, city, day
region, city, year, day
region, city, day
region, year, month, day
region, year, month
region, year
region, month, day
region, month
region, year, day
region, day
region
city, year, month, day
city, year, month
city, year
city, month, day
city, month
city, year, day
city, day
year, month, day
year, month
year
year, day
month, day
month
day
()

In the result sets that are generated by the GROUP BY operators, NULL has the following uses:
  • If a grouping column contains NULL, all null values are considered equal, and they are put into one NULL group.
  • When a column is aggregated in a row, the value of the column is shown as NULL.
The following example uses the GROUPING function to show the two uses of NULL. UNKNOWN replaces NULL in rows where the nulls in a column have been grouped. ALL replaces NULL in a column where NULL indicates that a column has been included in an aggregation.
USE tempdb;
GO
CREATE TABLE dbo.GroupingNULLS (
    Store nvarchar(19)
    ,SaleYear nvarchar(4)
    ,SaleMonth nvarchar (7))
INSERT INTO dbo.GroupingNULLS VALUES
(NULL,NULL,'January')
,(NULL,'2002',NULL)
,(NULL,NULL,NULL)
,('Active Cycling',NULL ,'January')
,('Active Cycling','2002',NULL)
,('Active Cycling',NULL ,NULL)
,('Active Cycling',NULL,'January')
,('Active Cycling','2003','Febuary')
,('Active Cycling','2003',NULL)
,('Mountain Bike Store','2002','January')
,('Mountain Bike Store','2002',NULL)
,('Mountain Bike Store',NULL,NULL)
,('Mountain Bike Store','2003','January')
,('Mountain Bike Store','2003','Febuary')
,('Mountain Bike Store','2003','March');

SELECT ISNULL(Store,
    CASE WHEN GROUPING(Store) = 0 THEN 'UNKNOWN' ELSE 'ALL' END)
    AS Store
    ,ISNULL(CAST(SaleYear AS nvarchar(7)),
    CASE WHEN GROUPING(SaleYear)= 0 THEN 'UNKNOWN' ELSE 'ALL' END)
    AS SalesYear
    ,ISNULL(SaleMonth,
    CASE WHEN GROUPING(SaleMonth) = 0 THEN 'UNKNOWN' ELSE 'ALL'END)
    AS SalesMonth
    ,COUNT(*) AS Count
FROM dbo.GroupingNULLS 
GROUP BY ROLLUP(Store, SaleYear, SaleMonth);
Here is the result set.
StoreSalesYearSalesMonthCount
UnknownUnknownUnknown1
UnknownUnknownJanuary1
UnknownUnknownALL2
Unknown2002Unknown1
Unknown2002ALL1
UnknownALLALL3
Active CyclingUnknownUnknown1
Active CyclingUnknownJanuary2
Active CyclingUnknownALL3
Active Cycling2002Unknown1
Active Cycling2002ALL1
Active Cycling2003Unknown1
Active Cycling2003February1
Active Cycling2003ALL2
Active CyclingALLALL6
Mountain Bike StoreUnknownUnknown1
Mountain Bike StoreUnknownALL1
Mountain Bike Store2002Unknown1
Mountain Bike Store2002January1
Mountain Bike Store2002ALL2
Mountain Bike Store2003February1
Mountain Bike Store2003January1
Mountain Bike Store2003March1
Mountain Bike Store2003ALL3
Mountain Bike StoreALLALL6
ALLALLALL15

The examples in this section use the SUM aggregate function so that the result sets can be compared. The other aggregate functions might also be used to calculate different summaries.

A. Using a simple GROUP BY

In the following example, the simple GROUP BY returns a result set to compare to the result sets of examples B through K. These examples use the GROUP BY operators with the same SELECT statement.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer C
    INNER JOIN Sales.Store S
        ON C.StoreID  = S.BusinessEntityID
    INNER JOIN Sales.SalesTerritory T
        ON C.TerritoryID  = T.TerritoryID 
    INNER JOIN Sales.SalesOrderHeader H
        ON C.CustomerID = H.CustomerID
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 290, 288)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID
ORDER BY T.[Group], T.CountryRegionCode
    ,S.Name,H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
EuropeDEVersatile Sporting Goods Company284859.232
EuropeDEVersatile Sporting Goods Company28917691.83
EuropeFRSpa and Exercise Outfitters28432774.36
EuropeFRSpa and Exercise Outfitters286246272.4

B. Using GROUP BY ROLLUP

In the following example, the ROLLUP operator returns a result set that contains the following groupings:
  • Region, Country, Store, and SalesPersonID
  • Region, Country, and Store
  • Region, and Country
  • Region
  • grand total
The number of groupings that is generated by ROLLUP is the same as the number of columns in the ROLLUP list plus a grand total grouping. The number of rows in a grouping is determined by the number of unique combinations of values in the columns of the grouping.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales' 
FROM Sales.Customer C
    INNER JOIN Sales.Store S
        ON C.StoreID  = S.BusinessEntityID
    INNER JOIN Sales.SalesTerritory T
        ON C.TerritoryID  = T.TerritoryID 
    INNER JOIN Sales.SalesOrderHeader H
        ON C.CustomerID = H.CustomerID
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 290, 288)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY ROLLUP(
    T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID)
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL297597.8
EuropeNULLNULLNULL297597.8
EuropeDENULLNULL18551.07
EuropeDEVersatile Sporting Goods CompanyNULL18551.07
EuropeDEVersatile Sporting Goods Company284859.232
EuropeDEVersatile Sporting Goods Company28917691.83
EuropeFRNULLNULL279046.8
EuropeFRSpa and Exercise OutfittersNULL279046.8
EuropeFRSpa and Exercise Outfitters28432774.36
EuropeFRSpa and Exercise Outfitters286246272.4

C. Using GROUP BY ROLLUP with the column order reversed

In the following example, the ROLLUP operator returns a result set that contains the following groupings:
  • SalesPersonID, Store, Country, and Region
  • SalesPersonID, Store, and Country
  • SalesPersonID, and Store
  • SalesPersonID
  • grand total
The columns in the ROLLUP list are the same as those in example B, but they are in the opposite order. Columns are rolled up from right to left; therefore, the order affects the groupings. The number of rows in the result set might vary with the column order.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer C
    INNER JOIN Sales.Store S
        ON C.StoreID  = S.BusinessEntityID 
    INNER JOIN Sales.SalesTerritory T
        ON C.TerritoryID  = T.TerritoryID 
    INNER JOIN Sales.SalesOrderHeader H
        ON C.CustomerID = H.CustomerID
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 290, 288)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY ROLLUP(
    H.SalesPersonID, S.Name, T.CountryRegionCode, T.[Group])
ORDER BY H.SalesPersonID, S.Name, T.CountryRegionCode, T.[Group];
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL297597.8
NULLNULLNULL28433633.59
NULLNULLSpa and Exercise Outfitters28432774.36
NULLFRSpa and Exercise Outfitters28432774.36
EuropeFRSpa and Exercise Outfitters28432774.36
NULLNULLVersatile Sporting Goods Company284859.232
NULLDEVersatile Sporting Goods Company284859.232
EuropeDEVersatile Sporting Goods Company284859.232
NULLNULLNULL286246272.4
NULLNULLSpa and Exercise Outfitters286246272.4
NULLFRSpa and Exercise Outfitters286246272.4
EuropeFRSpa and Exercise Outfitters286246272.4
NULLNULLNULL28917691.83
NULLNULLVersatile Sporting Goods Company28917691.83
NULLDEVersatile Sporting Goods Company28917691.83
EuropeDEVersatile Sporting Goods Company28917691.83

D. Using GROUP BY with concatenated ROLLUP operations

In the following example, the cross product of the two ROLLUP operations is returned.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,DATEPART(yyyy,OrderDate) AS 'Year'
    ,DATEPART(mm,OrderDate) AS 'Month'
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer C
    INNER JOIN Sales.Store S
        ON C.StoreID  = S.BusinessEntityID 
    INNER JOIN Sales.SalesTerritory T
        ON C.TerritoryID  = T.TerritoryID 
    INNER JOIN Sales.SalesOrderHeader H
        ON C.CustomerID = H.CustomerID
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND DATEPART(yyyy,OrderDate) = '2006'
GROUP BY 
    ROLLUP(T.[Group], T.CountryRegionCode)
    ,ROLLUP(DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate))
ORDER BY T.[Group], T.CountryRegionCode
    ,DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate);
Here is the result set.
RegionCountryYearMonthTotal Sales
NULLNULLNULLNULL966221.9606
NULLNULL2006NULL966221.9606
NULLNULL20067109936.0248
NULLNULL20068296651.4808
NULLNULL20069184477.7563
NULLNULL20061062792.5455
NULLNULL200611213238.0125
NULLNULL20061299126.1407
EuropeNULLNULLNULL966221.9606
EuropeNULL2006NULL966221.9606
EuropeNULL20067109936.0248
EuropeNULL20068296651.4808
EuropeNULL20069184477.7563
EuropeNULL20061062792.5455
EuropeNULL200611213238.0125
EuropeNULL20061299126.1407
EuropeFRNULLNULL966221.9606
EuropeFR2006NULL966221.9606
EuropeFR20067109936.0248
EuropeFR20068296651.4808
EuropeFR20069184477.7563
EuropeFR20061062792.5455
EuropeFR200611213238.0125
EuropeFR20061299126.1407

E. Using GROUP BY CUBE

In the following example, the CUBE operator returns a result set that has one grouping for all possible combinations of columns in the CUBE list and a grand total grouping.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 288, 290)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY CUBE(
    T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID)
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL254013.6014
NULLNULLNULL28728461.1854
NULLNULLNULL28817073.0655
NULLNULLNULL290208479.3505
NULLNULLSpa and Exercise OutfittersNULL236210.9015
NULLNULLSpa and Exercise Outfitters28727731.551
NULLNULLSpa and Exercise Outfitters290208479.3505
NULLNULLVersatile Sporting Goods CompanyNULL17802.6999
NULLNULLVersatile Sporting Goods Company287729.6344
NULLNULLVersatile Sporting Goods Company28817073.0655
NULLDENULLNULL17802.6999
NULLDENULL287729.6344
NULLDENULL28817073.0655
NULLDEVersatile Sporting Goods CompanyNULL17802.6999
NULLDEVersatile Sporting Goods Company287729.6344
NULLDEVersatile Sporting Goods Company28817073.0655
NULLFRNULLNULL236210.9015
NULLFRNULL28727731.551
NULLFRNULL290208479.3505
NULLFRSpa and Exercise OutfittersNULL236210.9015
NULLFRSpa and Exercise Outfitters28727731.551
NULLFRSpa and Exercise Outfitters290208479.3505
EuropeNULLNULLNULL254013.6014
EuropeNULLNULL28728461.1854
EuropeNULLNULL28817073.0655
EuropeNULLNULL290208479.3505
EuropeNULLSpa and Exercise OutfittersNULL236210.9015
EuropeNULLSpa and Exercise Outfitters28727731.551
EuropeNULLSpa and Exercise Outfitters290208479.3505
EuropeNULLVersatile Sporting Goods CompanyNULL17802.6999
EuropeNULLVersatile Sporting Goods Company287729.6344
EuropeNULLVersatile Sporting Goods Company28817073.0655
EuropeDENULLNULL17802.6999
EuropeDENULL287729.6344
EuropeDENULL28817073.0655
EuropeDEVersatile Sporting Goods CompanyNULL17802.6999
EuropeDEVersatile Sporting Goods Company287729.6344
EuropeDEVersatile Sporting Goods Company28817073.0655
EuropeFRNULLNULL236210.9015
EuropeFRNULL28727731.551
EuropeFRNULL290208479.3505
EuropeFRSpa and Exercise OutfittersNULL236210.9015
EuropeFRSpa and Exercise Outfitters28727731.551
EuropeFRSpa and Exercise Outfitters290208479.3505

F. Using CUBE with composite elements

In the following example, the CUBE operator returns a result set that has one grouping for all possible combinations of columns in the CUBE list and a grand total grouping.
The operator processes the grouped columns (T.[Group], T.CountryRegionCode) and (DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate)) each as a single column.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,DATEPART(yyyy,OrderDate) AS 'Year'
    ,DATEPART(mm,OrderDate) AS 'Month'
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer C
    INNER JOIN Sales.Store S
        ON C.StoreID  = S.BusinessEntityID 
    INNER JOIN Sales.SalesTerritory T
        ON C.TerritoryID  = T.TerritoryID 
    INNER JOIN Sales.SalesOrderHeader H
        ON C.CustomerID = H.CustomerID
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND DATEPART(yyyy,OrderDate) = '2006'
GROUP BY CUBE(
    (T.[Group], T.CountryRegionCode)
    ,(DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate)))
ORDER BY T.[Group], T.CountryRegionCode
    ,DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate);
Here is the result set.
RegionCountryYearMonthTotal Sales
NULLNULLNULLNULL966221.9606
NULLNULL20067109936.0248
NULLNULL20068296651.4808
NULLNULL20069184477.7563
NULLNULL20061062792.5455
NULLNULL200611213238.0125
NULLNULL20061299126.1407
EuropeFRNULLNULL966221.9606
EuropeFR20067109936.0248
EuropeFR20068296651.4808
EuropeFR20069184477.7563
EuropeFR20061062792.5455
EuropeFR200611213238.0125
EuropeFR20061299126.1407

G. Using GROUP BY with GROUPING SETS

In the following example, the GROUPING SETS operator has four groupings, one for each column in the SELECT list. The operator returns one row for each unique value in the Region, Country, Store, and SalesPersonID columns.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer 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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 288, 290)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY GROUPING SETS
    (T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID)
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULL28728461.1854
NULLNULLNULL28817073.0655
NULLNULLNULL290208479.3505
NULLNULLSpa and Exercise OutfittersNULL236210.9015
NULLNULLVersatile Sporting Goods CompanyNULL17802.6999
NULLDENULLNULL17802.6999
NULLFRNULLNULL236210.9015
EuropeNULLNULLNULL254013.6014

H. Using GROUPING SETS with composite elements

In the following example, the GROUPING SETS list contains two composite elements, (T.[Group], T.CountryRegionCode) and (DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate)). Each composite element is treated as one column.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,DATEPART(yyyy,OrderDate) AS 'Year'
    ,DATEPART(mm,OrderDate) AS 'Month'
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer 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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND DATEPART(yyyy,OrderDate) = '2006'
GROUP BY GROUPING SETS(
    (T.[Group], T.CountryRegionCode)
    ,(DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate)))
ORDER BY T.[Group], T.CountryRegionCode
    ,DATEPART(yyyy,OrderDate), DATEPART(mm,OrderDate);
Here is the result set.
RegionCountryYearMonthTotal Sales
NULLNULL20067109936.0248
NULLNULL20068296651.4808
NULLNULL20069184477.7563
NULLNULL20061062792.5455
NULLNULL200611213238.0125
NULLNULL20061299126.1407
EuropeFRNULLNULL966221.9606

I. Using GROUP BY with multiple GROUPING SETS

In the following example, the GROUPING SETS list has five elements. The result set has one row for the following elements:
  • Each unique combination of values in the Region and Country columns
  • Each unique value in the Store column
  • Each unique combination of values in the SalesPersonID and Region columns
  • Each unique value in the SalesPersonID column
  • A grand total
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer 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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 288, 290)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY GROUPING SETS(
    (T.[Group], T.CountryRegionCode)
    ,(S.Name)
    ,(H.SalesPersonID,T.[Group])
    ,(H.SalesPersonID)
    ,())
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL254013.6014
NULLNULLNULL28728461.1854
NULLNULLNULL28817073.0655
NULLNULLNULL290208479.3505
NULLNULLSpa and Exercise OutfittersNULL236210.9015
NULLNULLVersatile Sporting Goods CompanyNULL17802.6999
EuropeNULLNULL28728461.1854
EuropeNULLNULL28817073.0655
EuropeNULLNULL290208479.3505
EuropeDENULLNULL17802.6999
EuropeFRNULLNULL236210.9015

J. Using GROUPING SETS with a ROLLUP of part of the GROUP BY list

In the following example, the GROUPING SETS list includes groupings for columns T.[Group] and T.CountryRegionCode and a ROLLUP of columns S.Name and H.SalesPersonID.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer 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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 288, 290)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY GROUPING SETS(
    T.[Group], T.CountryRegionCode
   ,ROLLUP(S.Name, H.SalesPersonID))
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL254013.6014
NULLNULLSpa and Exercise OutfittersNULL236210.9015
NULLNULLSpa and Exercise Outfitters28727731.551
NULLNULLSpa and Exercise Outfitters290208479.3505
NULLNULLVersatile Sporting Goods CompanyNULL17802.6999
NULLNULLVersatile Sporting Goods Company287729.6344
NULLNULLVersatile Sporting Goods Company28817073.0655
NULLDENULLNULL17802.6999
NULLFRNULLNULL236210.9015
EuropeNULLNULLNULL254013.6014

K. Using GROUPING SETS with a CUBE of part of the GROUP BY list

In the following example, the GROUPING SETS list includes groupings for columns T.[Group] and T.CountryRegionCode and a CUBE of columns S.Name and H.SalesPersonID.
USE AdventureWorks2008R2;
GO
SELECT T.[Group] AS N'Region', T.CountryRegionCode AS N'Country'
    ,S.Name AS N'Store', H.SalesPersonID
    ,SUM(TotalDue) AS N'Total Sales'
FROM Sales.Customer 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
WHERE T.[Group] = N'Europe'
    AND T.CountryRegionCode IN(N'DE', N'FR')
    AND H.SalesPersonID IN(287, 288, 290)
    AND SUBSTRING(S.Name,1,4)IN(N'Vers', N'Spa ')
GROUP BY GROUPING SETS(
    T.[Group], T.CountryRegionCode
    ,CUBE(S.Name, H.SalesPersonID))
ORDER BY T.[Group], T.CountryRegionCode, S.Name, H.SalesPersonID;
Here is the result set.
RegionCountryStoreSalesPersonIDTotal Sales
NULLNULLNULLNULL254013.6014
NULLNULLNULL28728461.1854
NULLNULLNULL28817073.0655
NULLNULLNULL290208479.3505
NULLNULLSpa and Exercise OutfittersNULL236210.9015
NULLNULLSpa and Exercise Outfitters28727731.551
NULLNULLSpa and Exercise Outfitters290208479.3505
NULLNULLVersatile Sporting Goods CompanyNULL17802.6999
NULLNULLVersatile Sporting Goods Company287729.6344
NULLNULLVersatile Sporting Goods Company28817073.0655
NULLDENULLNULL17802.6999
NULLFRNULLNULL236210.9015
EuropeNULLNULLNULL254013.6014


No comments:

Post a Comment