您的位置:首页 > 数据库 > Oracle

ROLLUP和CUBE语句。 ORACLE分组统计

2009-12-02 21:12 465 查看
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
)
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: