`

ROLLUP和CUBE语句

阅读更多
Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句。如果是ROLLUP(A, B, C)的话,首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。如果是GROUP BY CUBE(A, B, C),则首先会对(A、B、C)进行GROUP BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP BY操作。 grouping_id()可以美化效果:


Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句。

除本文内容外,你还可参考:
分析函数参考手册: http://xsb.itpub.net/post/419/33028
分析函数使用例子介绍:http://xsb.itpub.net/post/419/44634

SQL> create table t as select * from dba_indexes;

表已创建。

SQL> select index_type, status, count(*) from t group by index_type, status;

INDEX_TYPE STATUS COUNT(*)
--------------------------- -------- ----------
LOB VALID 51
NORMAL N/A 25
NORMAL VALID 479
CLUSTER VALID 11

下面来看看ROLLUP和CUBE语句的执行结果。

SQL> select index_type, status, count(*) from t group by rollup(index_type, status);

INDEX_TYPE STATUS COUNT(*)
--------------------------- -------- ----------
LOB VALID 51
LOB 51
NORMAL N/A 25
NORMAL VALID 479
NORMAL 504
CLUSTER VALID 11
CLUSTER 11
566

已选择8行。

SQL> select index_type, status, count(*) from t group by cube(index_type, status);

INDEX_TYPE STATUS COUNT(*)
--------------------------- -------- ----------
566
N/A 25
VALID 541
LOB 51
LOB VALID 51
NORMAL 504
NORMAL N/A 25
NORMAL VALID 479
CLUSTER 11
CLUSTER VALID 11

已选择10行。

查询结果不是很一目了然,下面通过Oracle提供的函数GROUPING来整理一下查询结果。

SQL> select grouping(index_type) g_ind, grouping(status) g_st, index_type, status, count(*)
2 from t group by rollup(index_type, status) order by 1, 2;

G_IND G_ST INDEX_TYPE STATUS COUNT(*)
---------- ---------- --------------------------- -------- ----------
0 0 LOB VALID 51
0 0 NORMAL N/A 25
0 0 NORMAL VALID 479
0 0 CLUSTER VALID 11
0 1 LOB 51
0 1 NORMAL 504
0 1 CLUSTER 11
1 1 566

已选择8行。

这个查询结果就直观多了,和不带ROLLUP语句的GROUP BY相比,ROLLUP增加了对INDEX_TYPE的GROUP BY统计和对所有记录的GROUP BY统计。

也就是说,如果是ROLLUP(A, B, C)的话,首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。

下面看看CUBE语句。

SQL> select grouping(index_type) g_ind, grouping(status) g_st, index_type, status, count(*)
2 from t group by cube(index_type, status) order by 1, 2;

G_IND G_ST INDEX_TYPE STATUS COUNT(*)
---------- ---------- --------------------------- -------- ----------
0 0 LOB VALID 51
0 0 NORMAL N/A 25
0 0 NORMAL VALID 479
0 0 CLUSTER VALID 11
0 1 LOB 51
0 1 NORMAL 504
0 1 CLUSTER 11
1 0 N/A 25
1 0 VALID 541
1 1 566

已选择10行。

和ROLLUP相比,CUBE又增加了对STATUS列的GROUP BY统计。

如果是GROUP BY CUBE(A, B, C),则首先会对(A、B、C)进行GROUP BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP BY操作。

除了使用GROUPING函数,还可以使用GROUPING_ID来标识GROUP BY结果。

SQL> select grouping_id(index_type, status) g_ind, index_type, status, count(*)
2 from t group by rollup(index_type, status) order by 1;

G_IND INDEX_TYPE STATUS COUNT(*)
---------- --------------------------- -------- ----------
0 LOB VALID 51
0 NORMAL N/A 25
0 NORMAL VALID 479
0 CLUSTER VALID 11
1 LOB 51
1 NORMAL 504
1 CLUSTER 11
3 566

已选择8行。

SQL> select grouping_id(index_type, status) g_ind, index_type, status, count(*)
2 from t group by cube(index_type, status) order by 1;

G_IND INDEX_TYPE STATUS COUNT(*)
---------- --------------------------- -------- ----------
0 LOB VALID 51
0 NORMAL N/A 25
0 NORMAL VALID 479
0 CLUSTER VALID 11
1 LOB 51
1 NORMAL 504
1 CLUSTER 11
2 N/A 25
2 VALID 541
3 566

已选择10行。

grouping_id()可以美化效果:

select DECODE(GROUPING_ID(C1), 1, '合计', C1) D1,
DECODE(GROUPING_ID(C1, C2), 1, '小计', C2) D2,
DECODE(GROUPING_ID(C1, C2, C1 + C2), 1, '小计', C1 + C2) D3,
count(*),
GROUPING_ID(C1, C2, C1 + C2, C1 + 1, C2 + 1),
GROUPING_ID(C1)
from T2
group by rollup(C1, C2, C1 + C2, C1 + 1, C2 + 1);

===========================================================

1.报表合计专用的Rollup函数

销售报表

广州 1月 2000元

广州 2月 2500元

广州 4500元

深圳 1月 1000元

深圳 2月 2000元

深圳 3000元

所有地区 7500元

以往的查询SQL:

Select area,month,sum(money) from SaleOrder group by area,month

然后广州,深圳的合计和所有地区合计都需要在程序里自行累计

1.其实可以使用如下SQL:

Select area,month,sum(total_sale) from SaleOrder group by rollup(area,month)

就能产生和报表一模一样的纪录

2.如果year不想累加,可以写成

Select year,month,area,sum(total_sale) from SaleOrder group by year, rollup(month,area)

另外Oracle 9i还支持如下语法:

Select year,month,area,sum(total_sale) from SaleOrder group by rollup((year,month),area)

3.如果使用Cube(area,month)而不是RollUp(area,month),除了获得每个地区的合计之外,还将获得每个月份的合计,在报表最后显示。

4.Grouping让合计列更好读

RollUp在显示广州合计时,月份列为NULL,但更好的做法应该是显示为"所有月份"

Grouping就是用来判断当前Column是否是一个合计列,1为yes,然后用Decode把它转为"所有月份"

Select Decode(Grouping(area),1,'所有地区',area) area, Decode(Grouping(month),1,'所有月份',month), sum(money) From SaleOrder Group by RollUp(area,month);

2.对多级层次查询的start with.....connect by

比如人员组织,产品类别,Oracle提供了很经典的方法

SELECT LEVEL, name, emp_id,manager_emp_id FROM employee START WITH manager_emp_id is null CONNECT BY PRIOR emp_id = manager_emp_id;

上面的语句demo了全部的应用,start with指明从哪里开始遍历树,如果从根开始,那么它的manager应该是Null,如果从某个职员开始,可以写成emp_id='11'

CONNECT BY 就是指明父子关系,注意PRIOR位置

另外还有一个LEVEL列,显示节点的层次

3.更多报表/分析决策功能

3.1 分析功能的基本结构

分析功能() over( partion子句,order by子句,窗口子句)

概念上很难讲清楚,还是用例子说话比较好.

3.2 Row_Number 和 Rank, DENSE_Rank

用于选出Top 3 sales这样的报表

当两个业务员可能有相同业绩时,就要使用Rank和Dense_Rank

比如

金额 RowNum Rank Dense_Rank

张三 4000元 1 1 1

李四 3000元 2 2 2

钱五 2000元 3 3 3

孙六 2000元 4 3 3

丁七 1000元 5 5 4

这时,应该把并列第三的钱五和孙六都选进去,所以用Ranking功能比RowNumber保险.至于Desnse还是Ranking就看具体情况了。

SELECT salesperson_id, SUM(tot_sales) sp_sales, RANK( ) OVER (ORDER BY SUM(tot_sales) DESC) sales_rank FROM orders GROUP BY salesperson_id

3.3 NTILE 把纪录平分成甲乙丙丁四等

比如我想取得前25%的纪录,或者把25%的纪录当作同一个level平等对待,把另25%当作另一个Level平等对待

SELECT cust_nbr, SUM(tot_sales) cust_sales, NTILE(4) OVER (ORDER BY SUM(tot_sales) DESC) sales_quartile FROM orders GROUP BY cust_nbr ORDER BY 3,2 DESC;

NTITLE(4)把纪录以 SUM(tot_sales)排序分成4份.

3.4 辅助分析列和Windows Function

报表除了基本事实数据外,总希望旁边多些全年总销量,到目前为止的累计销量,前后三个月的平均销量这样的列来参考.

这种前后三个月的平均和到目前为止的累计销量就叫windows function, 见下例

SELECT month, SUM(tot_sales) monthly_sales, SUM(SUM(tot_sales)) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_preceeding FROM orders GROUP BY month ORDER BY month;

SELECT month, SUM(tot_sales) monthly_sales, AVG(SUM(tot_sales)) OVER (ORDER BY month ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) rolling_avg FROM orders GROUP BY month ORDER BY month;

Windows Function的关键就是Windows子句的几个取值

1 PRECEDING 之前的一条记录

1 FOLLOWING 之后的一条记录

UNBOUNDED PRECEDING 之前的所有记录

CURRENT ROW 当前纪录

4.SubQuery总结

SubQuery天天用了,理论上总结一下.SubQuery 分三种

1.Noncorrelated 子查询 最普通的样式.

2.Correlated Subqueries 把父查询的列拉到子查询里面去,头一回cyt教我的时候理解了半天.

3.Inline View 也被当成最普通的样式用了.

然后Noncorrelated 子查询又有三种情况

1.返回一行一列 where price < (select max(price) from goods )

2.返回多行一列 where price>= ALL (select price from goods where type=2)

or where NOT price< ANY(select price from goods where type=2)

最常用的IN其实就是=ANY()

3.返回多行多列 一次返回多列当然就节省了查询时间

UPDATE monthly_orders SET (tot_orders, max_order_amt) = (SELECT COUNT(*), MAX(sale_price) FROM cust_order) DELETE FROM line_item WHERE (order_nbr, part_nbr) IN (SELECT order_nbr, part_nbr FROM cust_order c)

========================================
/*--------理解grouping sets
select a, b, c, sum( d ) from t
group by grouping sets ( a, b, c )

等效于

select * from (
select a, null, null, sum( d ) from t group by a
union all
select null, b, null, sum( d ) from t group by b
union all
select null, null, c, sum( d ) from t group by c
)
*/
分享到:
评论

相关推荐

    SQL语句中Group BY 和Rollup以及cube用法

    ### SQL语句中Group BY 和Rollup以及Cube用法 #### Group BY 子句 `GROUP BY`子句是SQL查询中的一个非常重要的部分,它用于将数据表中的行按照一个或多个列进行分组,使得可以对每个分组执行聚合函数(如SUM、...

    SQL语句中Group BY 和Rollup以及cube用法.txt

    SQL Server中的用法为group by colomn with [rollup|cube],首先要弄明白rollup 和cube,就要知道group by的用法,group by 为对列进行分组,只展现分组统计的值,而 rollup 为分层次展现,cube 为展现列中所有层次...

    GROUP BY子句(rollup,cube,grouping sets)实例说明

    GROUP BY 子句(rollup, ...GROUP BY 语句用于基本的分组,GROUP BY ROLLUP 语句用于生成所有可能的分组结果,GROUP BY CUBE 语句用于生成所有可能的组合结果,GROUP BY GROUPING SETS 语句用于生成指定的分组结果。

    group by分组函数之rollup与cube用法1

    而在GROUP BY的基础上,Oracle数据库提供了两种高级分组功能:ROLLUP和CUBE,它们允许我们更灵活地生成汇总数据。 1. ROLLUP(滚联回溯): ROLLUP是GROUP BY的一个扩展,它不仅返回每个单独的分组结果,还会生成...

    rollup及cube的使用

    综上所述,`ROLLUP`和`CUBE`是在Oracle数据库中进行多维数据分析的强大工具,它们可以帮助我们轻松地生成不同级别的汇总数据。同时,结合使用`GROUPING`和`GROUPING_ID`函数,可以让查询结果更易于理解和分析。这些...

    Sql学习第四天——SQL 关于with cube,with rollup和grouping解释及演示

    `CUBE`和`ROLLUP`是`WITH`子句中的两个特殊运算符,它们主要用于多维度数据分析和聚合操作,通常在`GROUP BY`语句中配合使用。 1. **CUBE运算符**: `CUBE`生成的结果集包含了所有可能的子集,即所选列中值的所有...

    SQLServer中汇总功能的使用GROUPING,ROLLUP和CUBE

    然而,GROUP BY还可以与GROUPING、ROLLUP和CUBE运算符结合使用,以实现更复杂的多维度汇总功能。这些高级的汇总方法在数据分析和报表生成中非常有用,尤其是在处理大型数据集时。 GROUPING运算符主要用于识别汇总行...

    cube与rollup学习总结

    在数据库查询语言中,`CUBE`和`ROLLUP`是两种非常重要的分组函数,它们主要用于复杂的数据汇总和分析。这两种函数可以帮助我们以多种方式对数据进行分组和聚合,从而更好地理解数据集中的模式和趋势。本文将详细介绍...

    group by 后 使用 rollup 子句 总结.doc

    ### Group By 后使用 Rollup 子句的理解与应用 #### 一、Rollup 子句的基本...通过这些例子可以看出,`ROLLUP` 和 `CUBE` 都能够提供更丰富的数据分组选项,但在具体应用场景中应根据实际需求选择合适的子句来使用。

    ROLLUP的数据统计效果

    在数据库管理领域,`ROLLUP` 是一种用于生成汇总数据的SQL构造,它在多级分组时非常有用,...在使用`ROLLUP` 时,理解其生成的`NULL` 值的含义以及如何结合其他SQL语句进行数据筛选和排序,是提高数据分析效率的关键。

    SQLSERVER中union,cube,rollup,cumpute运算符使用说明

    在SQLSERVER中,有四种特殊的运算符用于处理和汇总数据:UNION、CUBE、ROLLUP和COMPUTE。这些运算符在数据查询和分析时非常有用,尤其在处理多个数据源合并、多维数据分析和自定义汇总计算时。 首先,我们来详细...

    sql字符处理函数大全

    ROLLUP是一个用于生成汇总数据的SQL语句特性,它允许在GROUP BY子句中对数据进行多级别的分组和汇总。例如,在给定的数据集中,我们有`col_a`、`col_b`和`col_c`三个列。当使用`GROUP BY rollup(col_a, col_b)`时,...

    postgresql 开发指南

    Postgresql 支持 ROLLUP 语句,使用 ROLLUP 语句可以对表中的数据进行分组,并且可以对分组结果进行 weiter grouping。例如: ```sql SELECT * FROM test GROUP BY ROLLUP (A, B, C); ``` Cube 语句 Postgresql ...

    Oracle分组统计

    分组统计可以分为多种类型,我们常用的有三个:Grouping Sets、Rollup 和 Cube。这三种类型都可以用来实现分组统计,但它们之间有所区别。 首先,我们来说说 Grouping Sets。Grouping Sets 是一种特殊的分组统计...

    SQL语句的执行原理及顺序

    7. CUBE 或 ROLLUP 选项:应用 CUBE 或 ROLLUP 选项,为 vt5 生成超组,生成 vt6。 8. HAVING 筛选器:应用 HAVING 筛选器,生成 vt7。 9. SELECT 列表:将 vt7 中的在 SELECT 中出现的列筛选出来,生成 vt8。 10. ...

    详解SQL中Groupings Sets 语句的功能和底层实现逻辑.doc

    通过Grouping Sets,我们可以实现类似于ROLLUP和CUBE的效果,但更为灵活。ROLLUP会产生所有可能的子集,而CUBE则会生成所有可能的全排列。GROUPING SETS则允许我们指定具体想要的分组组合,因此在某些场景下更为实用...

Global site tag (gtag.js) - Google Analytics