ROLLUP Extension to GROUP BY Rollup可以令select 语句根据group的维计算多层小计。他也可以计算总计。Rollup是对group by的简单扩展,所以他的语法非常简单。Rollup扩展非常高效,对一个查询增加的非常少的开销。 Rollup的行为非常直接,它根据grouping list的Rollup条款创建小计。它从右向左的进行再聚合。 首先,它计算grouping条款的标准聚合。 然后,它按照grouping list列从右向左的顺序进行更高层的聚合。 最后,创建n+1层的总计。N = grouping列的数量。 例如,一个查询用Rollup在grouping list列出time,region,department,结果集包括4个聚合层次。使用Rollup可以压缩数据。这对于对旧有分区较少更新的情况十分有用。
When to Use ROLLUP 一般在任务中包含小计的情况可以使用Rollup扩展。 ROLLUP Syntax Rollup出现在select查询的group by条款。他的形式是: Select … Group by Rollup(grouping_column_reference_list) Select channel_desc, calendar_month_desc, contry_id, sum(amount_sold) SALES$ From sales,customers,times,channels Where sales.time_id=times.time_id And sales.cust_id = customer.cust_id And sales.channel_id = channels.channel_id And channels.channel_desc IN ( ‘direct sales’,’Internet’) And times.calendar_month_desc IN (‘2000-09’,’2000-10’) And country_id IN (‘UK’,’US’) Group by rollup (channel_desc,calendar_month_desc,contry_id); CHANNEL_DESC CALENDAR CO SALES$ -------------------- -------- -- -------------- Direct Sales 2000-09 UK 1,378,126 Direct Sales 2000-09 US 2,835,557 Direct Sales 2000-09 4,213,683 Direct Sales 2000-10 UK 1,388,051 Direct Sales 2000-10 US 2,908,706 Direct Sales 2000-10 4,296,757 Direct Sales 8,510,440 Internet 2000-09 UK 911,739 Internet 2000-09 US 1,732,240 Internet 2000-09 2,643,979 Internet 2000-10 UK 876,571 Internet 2000-10 US 1,893,753 Internet 2000-10 2,770,324 Internet 5,414,303 13,924,743
This query returns the following sets of rows:这个查询返回如下的行: 1. Group by条款规定的标准聚合 2. 基于country_id层的小计 3. 基于calendar_month_desc和country_id的2层聚合 4. 总计 Partial Rollup 部分rollup 你也可以使用Rollup包含有限的几个小计。部分rollup的语法是 Group by expr1,Rollup(expr2,expr3) 这种情况下,group by 条款创建2+1层的小记。 层次为(expr1,expr2,expr3)(expr1,expr2)(expr1)
select channel_desc, calendar_month_desc, country_id, sum(amount_sold) sales$ from sales,customers,times,channels Where sales.time_id=times.time_id And sales.cust_id = customer.cust_id And sales.channel_id = channels.channel_id And channels.channel_desc IN ( ‘direct sales’,’Internet’) And times.calendar_month_desc IN (‘2000-09’,’2000-10’) And country_id IN (‘UK’,’US’) Group by channel_desc,rollup(calendar_month_desc,country_id); CHANNEL_DESC CALENDAR CO SALES$ -------------------- -------- -- -------------- Direct Sales 2000-09 UK 1,378,126 Direct Sales 2000-09 US 2,835,557 Direct Sales 2000-09 4,213,683 Direct Sales 2000-10 UK 1,388,051 Direct Sales 2000-10 US 2,908,706 Direct Sales 2000-10 4,296,757 Direct Sales 8,510,440 Internet 2000-09 UK 911,739 Internet 2000-09 US 1,732,240 Internet 2000-09 2,643,979 Internet 2000-10 UK 876,571 Internet 2000-10 US 1,893,753 Internet 2000-10 2,770,324 Internet 5,414,303 这个查询返回下面的行 1. Group by条款规定的标准聚合 2. 基于country_id层的小计 3. 基于calendar_month_desc和country_id的2层聚合 4. 不计算总计 参考文档编号:a96520.pdf
When to Use CUBE 需要交叉报表的地方可以用Cube。交叉报表的数据生成可以通过简单的带有Cube的select查询语句实现。像Rollup,Cube在总结性报表中非常有用。Cube相比较一维多层,在多维的情况下更有用。 CUBE Syntax CUBE出现在select语句的group by条款中。它的形式是: Select … group by CUBE (group_column_reference_list) 例: select channel_desc, calendar_month_desc, country_id, sum(amount_sold) sales$ from sales,customers,times,channels Where sales.time_id=times.time_id And sales.cust_id = customer.cust_id And sales.channel_id = channels.channel_id And channels.channel_desc IN ( ‘direct sales’,’Internet’) And times.calendar_month_desc IN (‘2000-09’,’2000-10’) And country_id IN (‘UK’,’US’) Group by CUBE (channel_desc,calendar_month_desc,country_id); CHANNEL_DESC CALENDAR CO SALES$ -------------------- -------- -- -------------- Direct Sales 2000-09 UK 1,378,126 Direct Sales 2000-09 US 2,835,557 Direct Sales 2000-09 4,213,683 Direct Sales 2000-10 UK 1,388,051 Direct Sales 2000-10 US 2,908,706 Direct Sales 2000-10 4,296,757 Direct Sales UK 2,766,177 Direct Sales US 5,744,263 Direct Sales 8,510,440 Internet 2000-09 UK 911,739 Internet 2000-09 US 1,732,240 Internet 2000-09 2,643,979 Internet 2000-10 UK 876,571 Internet 2000-10 US 1,893,753 Internet 2000-10 2,770,324 Internet UK 1,788,310 Internet US 3,625,993 Internet 5,414,303 2000-09 UK 2,289,865 2000-09 US 4,567,797 2000-09 6,857,662 2000-10 UK 2,264,622 2000-10 US 4,802,459 2000-10 7,067,081 UK 4,554,487 US 9,370,256 13,924,743
Partial CUBE部分CUBE 部分CUBE类似部分ROLLUP,可以限制某些维度,还可以把一些列放在CUBE之外。这种情况下,所有可能的小节限制在CUBE列表之中。 部分CUBE 语法 GROUP BY expr1, CUBE(expr2, expr3) 计算4次小计: n (expr1, expr2, expr3) n (expr1, expr2) n (expr1, expr3) n (expr1) Calculating Subtotals Without CUBE不使用CUBE计算小计 像ROLLUP一样,多个select语句使用UNION ALL连接可以提供跟CUBE相同的信息。但是,却需要多个select语句。对于n维CUBE,需要2的n次方个select查询。 在3维的例子中,这意味着需要把这些select语句都通过UNION ALL联接起来。 这么多的select语句将会使得处理不够高效,并且加长sql语句。 GROUPING Functions ROLLUP和CUBE带来了两个问题。 第一, 你怎么让程序知道结果集哪一行代表小节,并且怎样知道对于一个给定的小节找到确切的聚合层次? 如果查询结果出现NULL还有CUBE ROLLUP产生的NULL,你如何来区分呢 GROUPING Function Grouping 解决上面的问题。使用一个列作为参数。Grouping当rollup 和 cube生成的NULL值时返回1。就是说如果这一列是个小节,则grouping返回1;否则返回0 Grouping 的语法 Grouping出现在select条款中,形如 Select … [grouping(dimension_column) … ] … Group by … {CUBE | ROLLUP | GROUPING SETS} (dimension_column)
举例 SELECT DECODE(GROUPING(channel_desc), 1, 'All Channels', hannel_desc) AS Channel, DECODE(GROUPING(country_id), 1, 'All Countries', country_id) AS Country, TO_CHAR(SUM(amount_sold), '9,999,999,999') SALES$ FROM sales, customers, times, channels WHERE sales.time_id=times.time_id AND sales.cust_id=customers.cust_id AND sales.channel_id= channels.channel_id AND channels.channel_desc IN ('Direct Sales', 'Internet') AND times.calendar_month_desc= '2000-09' AND country_id IN ('UK', 'US') GROUP BY CUBE(channel_desc, country_id)
CHANNEL COUNTRY SALES$ -------------------- ------------- -------------- Direct Sales UK 1,378,126 Direct Sales US 2,835,557 Direct Sales All Countries 4,213,683 Internet UK 911,739 Internet US 1,732,240 Internet All Countries 2,643,979 All Channels UK 2,289,865 All Channels US 4,567,797 All Channels All Countries 6,857,662
使用having子句来限制 HAVING (GROUPING(channel_desc)=1 AND GROUPING(calendar_month_desc)= 1 AND GROUPING(country_id)=1) OR (GROUPING(channel_desc)=1 AND GROUPING(calendar_month_desc)= 1) OR (GROUPING(country_id)=1 AND GROUPING(calendar_month_desc)= 1); 这样得到的全是聚合数据.
SELECT channel_desc, calendar_month_desc, country_id, TO_CHAR(SUM(amount_sold), '9,999,999,999') SALES$ FROM sales, customers, times, channels WHERE sales.time_id=times.time_id AND sales.cust_id=customers.cust_id AND sales.channel_id= channels.channel_id AND channels.channel_desc IN ('Direct Sales', 'Internet') AND times.calendar_month_desc IN ('2000-09', '2000-10') AND country_id IN ('UK', 'US') GROUP BY GROUPING SETS((channel_desc, calendar_month_desc, country_id), (channel_desc, country_id), (calendar_month_desc, country_id)); 这个语句计算3个grouping n (channel_desc, calendar_month_desc, country_id) n (channel_desc, country_id) n (calendar_month_desc, country_id)
CUBE( a , b , c) 等效于 Grouping sets ( (a,b,c), (a,b),(a,c),(b,c),(a),(b),(c),() ) 和 rollup(a,b,c) Composite Columns 组合列 组合列示列的集合在计算grouping的时候可以看作一个单元。
ROLLUP (year, (quarter, month), day)意思是 n (year, quarter, month, day), n (year, quarter, month), n (year) THE END 参考文档编号 a96520.pdf 参考文档名称 Oracle9i Data Warehousing Guide 第18章 部分词语不做翻译,例如group grouping CUBE rollup等等。