Lets try with some realtime example...
Create sales table and fill some data into it:
CREATE TABLE Sales (EmpId INT, Yr INT, Sales MONEY)
INSERT Sales VALUES(1, 2005, 12000)
INSERT Sales VALUES(1, 2006, 18000)
INSERT Sales VALUES(1, 2007, 25000)
INSERT Sales VALUES(2, 2005, 15000)
INSERT Sales VALUES(2, 2006, 6000)
INSERT Sales VALUES(3, 2006, 20000)
INSERT Sales VALUES(3, 2007, 24000)
Then run the bellow query:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY EmpId, Yr WITH ROLLUP
Output:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3zOUNRI8731ZXU7-tfT5QQfrVUKj9fxTY2r3cVx6qHGJ4aK2GZP5Ge0bh5cZ8U-HyzHbM4iRz2zQbmunOOkoaMincMNn5Fm-PAJHfOrCwASKsNM16KFkqRgQmdKq-xEeuTUJ5rXNGkSfm/s320/778868286.jpg)
Also try this:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY EmpId, Yr WITH CUBE
Output:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCpbhg-vEZWv9tjGEhEguCCFuBdavlnSSEsBFpO_fBm1oX6A5JFA7IzFGUZhlag3ewEXQCNJIqwjGZrK2LIrcDQ0jY8340oZ3WtM9Yme40fBwJht_WOuvvfhHaX33rpH6btQqncbcMc8eU/s320/778868286.jpg)
We can rewrite these two queries using the new syntax as:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY ROLLUP(EmpId, Yr)
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY CUBE(EmpId, Yr)
The new GROUPING SETS syntax is considerably more powerful. It allows us to specify precisely which aggregations we want to compute. As the following table illustrates, our simple two dimensional schema has a total of only four possible aggregations:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguFffQ5lsNgJX2voyKtd-WesFqjcbsjgYw__tiHzwI365do1_QGPfsGzQbbHO5QMbSur598hfFyO_Z6JwvgdcADJivm21zFBxzuZK63prcKtNAxyCGDfcqL1_NNYyEM5OgUQPfYaANdC6D/s320/778868286.jpg)
ROLLUP and CUBE are just shorthand for two common usages of GROUPING SETS. We can express the above ROLLUP query as:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr), (EmpId), ())
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-c3SEJRXcFrdLKNr_x9-ZuR7BmkLn6O4GOgNjBzID1bYPdE_fXEVBRkRUlfQbZXAFpl2wSGPVdEKchcyOM4rD3-xMF2WApHOIS4kEjnRiQFLLgBjpaX_hyVLGDe3kC0Wgvj27QGD7qoOn/s320/778868286.jpg)
This query explicitly asks SQL Server to aggregate sales by employee and year, to aggregate by employee only, and to compute the total for all employees for all years. The () syntax with no GROUP BY columns denotes the total. Similarly, we can express the above CUBE query by asking SQL Server to compute all possible aggregate combinations:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr), (EmpId), (Yr), ())
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglmRSaBG9mI8k0Vp9scC5AtUlp2-hcJ3jWD2xBx_hZp-UfHFbL6TypqDC5P55kGgH608xs20cVT6wlUwsx8NJW-eptIIEwUcOMjKoqyt6rM4H0HHRrEOzBNixg-sHiWGmrfdCM4KGtra_-/s320/778868286.jpg)
We can also use GROUPING SETS to compute other results. For example, we can perform a partial rollup aggregating sales by employee and year and by employee only but without computing the total for all employees for all years:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr), (EmpId))
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaESe2K95VIHPX3KpRl0c4cgWZOxPzc3vG69hqX4lmNyEITGv_ppiAbRNmBPZ5wXYCw94zBAqNwCv2wWHf4b7nH8CS1OIRD2HEQm9W78UKeJa40s7srFo-WV9-jDg-ljIcXDpNMEkQCtTU/s320/778868286.jpg)
We can skip certain rollup levels. For example, we can compute the total sales by employee and year and the total sales for all employees and all years without computing any of the intermediate results:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr), ())
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNI51WzMaX8p-dA1yRelzZsfd0YhZKrQuV5idTkuk6MjZhxUKmPlIqCtIa0sl8zdkn6NNSfUpGZEJQiS1UipPje1wzWBI5TBrl2Xe-zxe8AiBHfpGCbWG3yTnVYscbk7qUg2FQbd3c1JII/s320/778868286.jpg)
We can even compute multiple unrelated aggregations along disparate dimensions. For example, we can compute the total sales by employee and the total sales by year:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId), (Yr))
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifGTGe4RMjoyBkJ5hnnfgg_wr4ZT1La7HsuFrO09iv0PX1OxEJh_C_g6u33qsKWYAcmCi5wxVtXBUxBRQsgpLMrssuE094cCDVWZV4etVYpg9pJTyQ3FlxEaXESKoL3A8Wl44gZa7ourB5/s320/778868286.jpg)
Note that we could also write GROUPING SETS (EmpId, Yr) without the extra set of parenthesis, but the extra parenthesis make the intent of the query more explicit and clearly differentiate the previous query from the following query which just performs a normal aggregation by employee and year:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr))
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTjePUObfCjgxzpZSjamBH7WRByVhQylFUlw8EVVM2HTFYVL7bn9K3-1jxyjQDPK24681rn5rxRh6uUqQj-844Vp-QPfe8V_uJXL9YJRXexwAI4kvcfuOYdWLHMjcsozVMzqPecqGnD2Gk/s320/778868286.jpg)
Here are some additional points worth noting about the GROUPING SETS syntax:
As with any other aggregation query, if a column appears in the SELECT list and is not part of an aggregate function, it must appear somewhere in the GROUP BY clause. Thus, the following is not valid:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId), ())
Msg 8120, Level 16, State 1, Line 1
Column 'Sales.Yr' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
The order of the columns within each GROUPING SET and the order of the GROUPING SETS does not matter. So both of the following queries compute the same CUBE although the order that the rows are output differs:
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr), (EmpId), (Yr), ())
SELECT EmpId, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((), (Yr), (EmpId), (Yr, EmpId))
If the order that the rows are output matters, use an explicit ORDER BY clause to enforce that order.
We can nest CUBE and ROLLUP within a GROUPING SETS clause as shorthand for expressing more complex GROUPING SETS. This shorthand is most useful when we have more than three dimensions in our schema. For example, suppose we add a month column to our sales table:
CREATE TABLE Sales (EmpId INT, Month INT, Yr INT, Sales MONEY)
Now, suppose we want to compute sales for each employee by month and year, by year, and total. We could write out all of the GROUPING SETS explicitly:
SELECT EmpId, Month, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, Yr, Month), (EmpId, Yr), (EmpId))
Or we can use ROLLUP to simplify the query:
SELECT EmpId, Month, Yr, SUM(Sales) AS Sales
FROM Sales
GROUP BY GROUPING SETS((EmpId, ROLLUP(Yr, Month)))
Note that once again the correct use of parenthesis is critical. If we omit one set of parenthesis from the above query, the meaning changes significantly and we end up separately aggregating by employee and then computing the year and month ROLLUP for all employees.
No comments:
Post a Comment