A. rollup、cube、grouping sets区别:
如果是ROLLUP(A, B, C)的话,GROUP BY顺序
(A、B、C)
(A、B)
(A)
最后对全表进行GROUP BY操作。
如果是GROUP BY CUBE(A, B, C),GROUP BY顺序
(A、B、C)
(A、B)
(A、C)
(A)
(B、C)
(B)
(C),
最后对全表进行GROUP BY操作。
如果是 GROUP BY grouping SETS(A, B, C),GROUP BY顺序
首先对(A)进行GROUP BY
然后是(B)进行GROUP BY
最后是(C)进行GROUP BY
- 創建測試表
[oracle@DB01 ~]$ sql BUS/[email protected]:1521/MPBUS
SQL> SET SQLFORMAT ansiconsole
SQL> create table tmp1(CITY varchar2(20), PRODUCT varchar2(20), YEAR number, SALES number);
SQL>
insert into tmp1 values ('北京','彩電', 1999, 1000);
insert into tmp1 values ('北京','彩電', 2000, 2000);
insert into tmp1 values ('北京','彩電', 2001, 3000);
insert into tmp1 values ('北京','冰箱', 1999, 4000);
insert into tmp1 values ('北京','冰箱', 2000, 5000);
insert into tmp1 values ('北京','冰箱', 2001, 6000);
insert into tmp1 values ('天津','彩電', 1999, 1100);
insert into tmp1 values ('天津','彩電', 2000, 2100);
insert into tmp1 values ('天津','彩電', 2001, 3100);
insert into tmp1 values ('天津','冰箱', 1999, 4100);
insert into tmp1 values ('天津','冰箱', 2000, 5100);
insert into tmp1 values ('天津','冰箱', 2001, 6100);
commit;
SQL> select * from tmp1;
CITY PRODUCT YEAR SALES
北京 彩電 1999 1000
北京 彩電 2000 2000
北京 彩電 2001 3000
北京 冰箱 1999 4000
北京 冰箱 2000 5000
北京 冰箱 2001 6000
天津 彩電 1999 1100
天津 彩電 2000 2100
天津 彩電 2001 3100
天津 冰箱 1999 4100
天津 冰箱 2000 5100
天津 冰箱 2001 6100
- sum函数,统计总合
#按照年份,统计每個城市的总收入
SQL> select year, city, sum(sales)
from tmp1 group by year, city;
YEAR CITY SUM(SALES)
1999 北京 5000
2001 北京 9000
2000 北京 7000
2001 天津 9200
1999 天津 5200
2000 天津 7200
- rollup函数(A,B)
#按照年份,统计每個城市的总收入
#首先对(A、B)进行GROUP BY,
#然后是(A)进行GROUP BY,
#最后对全表进行GROUP BY操作
SQL> select year, city, sum(sales)
from tmp1 group by rollup(year, city)
order by year,city;
YEAR CITY SUM(SALES)
1999 北京 5000
1999 天津 5200
1999 10200
2000 北京 7000
2000 天津 7200
2000 14200
2001 北京 9000
2001 天津 9200
2001 18200
42600
SQL> select
decode(grouping(year),1,'全年',year) "年份"
,decode(grouping(city),1,'全市',city) "城市"
,sum(sales) "金额"
from tmp1 group by rollup(year, city)
order by year,city;
年份 城市 金额
1999 北京 5000
1999 天津 5200
1999 全市 10200
2000 北京 7000
2000 天津 7200
2000 全市 14200
2001 北京 9000
2001 天津 9200
2001 全市 18200
全年 全市 42600
- cube函数(A,B)
#按照年份,统计每個城市的总收入
#首先会对(A、B)进行GROUP BY,
#然后依次是(A),(B)
#最后对全表进行GROUP BY操作
SQL> select year, city, sum(sales)
from tmp1 group by cube(year, city)
order by year,city nulls last;
YEAR CITY SUM(SALES)
1999 北京 5000
1999 天津 5200
1999 10200
2000 北京 7000
2000 天津 7200
2000 14200
2001 北京 9000
2001 天津 9200
2001 18200
北京 21000
天津 21600
42600
#grouping函数
#在以上例子中,是用rollup和cube函数都会对结果集产生null,这时候可用grouping函数来确认
#该记录是由哪个字段得出来的
#grouping函数用法,带一个参数,参数为字段名,如果当前行是由rollup或者cube汇总得来的,结果就返回1,反之返回0
SQL> select
decode(grouping(year),1,'全年',year) "年份"
,decode(grouping(city),1,'全市',city) "城市"
,sum(sales) "金额"
from tmp1 group by cube(year, city)
order by year,city nulls last;
年份 城市 金额
1999 北京 5000
1999 天津 5200
1999 全市 10200
2000 北京 7000
2000 天津 7200
2000 全市 14200
2001 北京 9000
2001 天津 9200
2001 全市 18200
全年 北京 21000
全年 天津 21600
全年 全市 42600
- sets函数(A,B)
#按照年份,统计每個城市的总收入
#首先对(A)进行GROUP BY
#然后是(B)进行GROUP BY
SQL> select year, city, sum(sales)
from tmp1 group by grouping sets(year, city)
order by year,city;
YEAR CITY SUM(SALES)
1999 10200
2000 14200
2001 18200
北京 21000
天津 21600
SQL> select
decode(grouping(year),1,'全年',year) "年份"
,decode(grouping(city),1,'全市',city) "城市"
,sum(sales) "金额"
from tmp1 group by grouping sets(year, city)
order by year,city;
年份 城市 金额
1999 全市 10200
2000 全市 14200
2001 全市 18200
全年 北京 21000
全年 天津 21600
B.rank,dense_rank,row_number的区别:
结果集中如果出现两个相同的数据,那么rank会进行跳跃式的排名,
比如两个第1,那么没有第2接下来就是第3(如 1,1,3);
但是dense_rank不会跳跃式的排名,两个第1接下来还是第2(1,1,2);
row_number最牛,即使两个数据相同,排名也不一样(1,2,3)。
- 分析函数初始化数据
create table earnings -- 打工赚钱表
(
earnmonth varchar2(6), -- 打工月份
area varchar2(20), -- 打工地区
sname varchar2(20), -- 打工者姓名
times int, -- 本月打工次数
singleincome number(10,2), -- 每次赚多少钱
personincome number(10,2) -- 当月总收入
) ;
insert into earnings values('200912','北平','大魁',11,30,11*30);
insert into earnings values('200912','北平','大凯',8,25,8*25);
insert into earnings values('200912','北平','小东',30,6.25,30*6.25);
insert into earnings values('200912','北平','大亮',16,8.25,16*8.25);
insert into earnings values('200912','北平','贱敬',30,11,30*11);
insert into earnings values('200912','金陵','小玉',15,12.25,15*12.25);
insert into earnings values('200912','金陵','小凡',27,16.67,27*16.67);
insert into earnings values('200912','金陵','小妮',7,33.33,7*33.33);
insert into earnings values('200912','金陵','小俐',0,18,0);
insert into earnings values('200912','金陵','雪儿',11,9.88,11*9.88);
insert into earnings values('201001','北平','大魁',0,30,0);
insert into earnings values('201001','北平','大凯',14,25,14*25);
insert into earnings values('201001','北平','小东',19,6.25,19*6.25);
insert into earnings values('201001','北平','大亮',7,8.25,7*8.25);
insert into earnings values('201001','北平','贱敬',21,11,21*11);
insert into earnings values('201001','金陵','小玉',6,12.25,6*12.25);
insert into earnings values('201001','金陵','小凡',17,16.67,17*16.67);
insert into earnings values('201001','金陵','小妮',27,33.33,27*33.33);
insert into earnings values('201001','金陵','小俐',16,18,16*18);
insert into earnings values('201001','金陵','雪儿',11,9.88,11*9.88);
commit;
- rank() over开窗函数
#重复值所在行的序列值相同,但其后的序列值从重复行数开始递增(如1,1,3 【跳过2】)
#按照月份、地区,求打工收入排序
SQL> select earnmonth 月份,area 地区,sname 打工者, personincome 收入,
rank() over (partition by earnmonth,area order by personincome desc) 排名
from earnings;
月份 地区 打工者 收入 排名
200912 北平 大魁 330 1
200912 北平 贱敬 330 1
200912 北平 大凯 200 3
200912 北平 小东 187.5 4
200912 北平 大亮 132 5
200912 金陵 小凡 450.09 1
200912 金陵 小妮 233.31 2
200912 金陵 小玉 183.75 3
200912 金陵 雪儿 108.68 4
200912 金陵 小俐 0 5
...
- dense_rank() over开窗函数
#排序时如果遇到列有重复值,则重复值所在行的序列值相同,而其后的序列值依旧递增(如 1,1,2)
#按照月份、地区,求打工收入排序
SQL> select earnmonth 月份,area 地区,sname 打工者, personincome 收入,
dense_rank() over (partition by earnmonth,area order by personincome desc) 排名
from earnings;
月份 地区 打工者 收入 排名
200912 北平 大魁 330 1
200912 北平 贱敬 330 1
200912 北平 大凯 200 2
200912 北平 小东 187.5 3
200912 北平 大亮 132 4
200912 金陵 小凡 450.09 1
200912 金陵 小妮 233.31 2
200912 金陵 小玉 183.75 3
200912 金陵 雪儿 108.68 4
200912 金陵 小俐 0 5
...
- row_number() over
#不管是否有重复行,(分组内)序列值始终递增
#按照月份、地区,求打工收入排序
SQL> select earnmonth 月份,area 地区,sname 打工者, personincome 收入,
row_number() over (partition by earnmonth,area order by personincome desc) 排名
from earnings;
月份 地区 打工者 收入 排名
200912 北平 大魁 330 1
200912 北平 贱敬 330 2
200912 北平 大凯 200 3
200912 北平 小东 187.5 4
200912 北平 大亮 132 5
200912 金陵 小凡 450.09 1
200912 金陵 小妮 233.31 2
200912 金陵 小玉 183.75 3
200912 金陵 雪儿 108.68 4
200912 金陵 小俐 0 5
...
- sum累计求和 (逐条求和)
SQL> select earnmonth 月份,area 地区,sname 打工者,personincome as 收入
,sum(personincome) over (partition by earnmonth,area order by personincome) 逐条累加收入
from earnings;
月份 地区 打工者 收入 逐条累加收入
200912 北平 大亮 132 132
200912 北平 小东 187.5 319.5
200912 北平 大凯 200 519.5
200912 北平 大魁 330 1179.5
200912 北平 贱敬 330 1179.5
200912 金陵 小俐 0 0
200912 金陵 雪儿 108.68 108.68
200912 金陵 小玉 183.75 292.43
200912 金陵 小妮 233.31 525.74
200912 金陵 小凡 450.09 975.83
...
- max,min,avg和sum函数综合运用
#按照月份和地区求打工收入最高值,最低值,平均值和总额
SQL> select distinct earnmonth 月份, area 地区,
max(personincome) over(partition by earnmonth,area) 最高值,
min(personincome) over(partition by earnmonth,area) 最低值,
avg(personincome) over(partition by earnmonth,area) 平均值,
sum(personincome) over(partition by earnmonth,area) 总额
from earnings;
月份 地区 最高值 最低值 平均值 总额
200912 金陵 450.09 0 195.166 975.83
200912 北平 330 132 235.9 1179.5
...
SQL> select earnmonth 月份, area 地区,
2 max(personincome) over(partition by earnmonth,area) 最高值,
3 min(personincome) over(partition by earnmonth,area) 最低值,
4 avg(personincome) over(partition by earnmonth,area) 平均值,
5 sum(personincome) over(partition by earnmonth,area) 总额
6 from earnings;
月份 地区 最高值 最低值 平均值 总额
200912 北平 330 132 235.9 1179.5
200912 北平 330 132 235.9 1179.5
200912 北平 330 132 235.9 1179.5
200912 北平 330 132 235.9 1179.5
200912 北平 330 132 235.9 1179.5
200912 金陵 450.09 0 195.166 975.83
200912 金陵 450.09 0 195.166 975.83
200912 金陵 450.09 0 195.166 975.83
200912 金陵 450.09 0 195.166 975.83
200912 金陵 450.09 0 195.166 975.83
...
- lag和lead函数
#说明:Lag和Lead函数可以在一次查询中取出某个字段的前N行和后N行的数据(可以是其他字段的数据,比如根据字段甲查询上一行或下两行的字段乙)
#语法如下:
lag(value_expression [,offset] [,default]) over ([query_partition_clase] order_by_clause);
lead(value_expression [,offset] [,default]) over ([query_partition_clase] order_by_clause);
其中:
value_expression:可以是一个字段或一个内建函数。
offset是正整数,默认为1,指往前或往后几点记录.因组内第一个条记录没有之前的行,最后一行没有之后的行,
default就是用于处理这样的信息,默认为空。
#求出每个打工者上个月和下个月收入
SQL> select earnmonth 本月,sname 打工者,
lag(personincome,1,0) over(partition by sname order by earnmonth) 上月收入,
personincome as 本月收入,
lead(personincome,1,0) over(partition by sname order by earnmonth) 下月收入
from earnings order by sname,earnmonth;
本月 打工者 上月收入 本月收入 下月收入
200912 大亮 0 132 57.75
201001 大亮 132 57.75 0
200912 大凯 0 200 350
201001 大凯 200 350 0
200912 大魁 0 330 0
201001 大魁 330 0 0
...
- GROUP BY grouping sets(A, B, C)
#首先对(A)进行GROUP BY
#然后是(B)进行GROUP BY
#最后是(C)进行GROUP BY
SQL> select city, product, year, sum(sales)
from tmp1
group by grouping sets (city,product,year);
CITY PRODUCT YEAR SUM(SALES)
1999 10200
2001 18200
2000 14200
天津 21600
北京 21000
冰箱 30300
彩電 12300
or
SQL>
select city, null as product,null as year,sum(sales)
from tmp1
group by city
union all
select null city, product,null as year,sum(sales)
from tmp1
group by product
union all
select null city, null as product,year,sum(sales)
from tmp1
group by year;
CITY PRODUCT YEAR SUM(SALES)
天津 21600
北京 21000
冰箱 30300
彩電 12300
1999 10200
2001 18200
2000 14200
- GROUP BY CUBE(A, B, C)
#首先会对(A、B、C)进行GROUP BY,
#然后依次是(A、B),(A、C),(A),(B、C),(B),(C),
#最后对全表进行GROUP BY操作
SQL> select city, product, year, sum(sales)
from tmp1 group by CUBE(city,product,year)
order by city, product, year nulls last;
CITY PRODUCT YEAR SUM(SALES)
北京 冰箱 1999 4000
北京 冰箱 2000 5000
北京 冰箱 2001 6000
北京 冰箱 15000
北京 彩電 1999 1000
北京 彩電 2000 2000
北京 彩電 2001 3000
北京 彩電 6000
北京 1999 5000
北京 2000 7000
北京 2001 9000
北京 21000
天津 冰箱 1999 4100
天津 冰箱 2000 5100
天津 冰箱 2001 6100
天津 冰箱 15300
天津 彩電 1999 1100
天津 彩電 2000 2100
天津 彩電 2001 3100
天津 彩電 6300
天津 1999 5200
天津 2000 7200
天津 2001 9200
天津 21600
冰箱 1999 8100
冰箱 2000 10100
冰箱 2001 12100
冰箱 30300
彩電 1999 2100
彩電 2000 4100
彩電 2001 6100
彩電 12300
1999 10200
2000 14200
2001 18200
42600
- GROUP BY A,CUBE(B, C)
#首先会对(A、B、C)进行GROUP BY,
#然后依次是(A、B),(A、C)
#最后对(A)进行GROUP BY操作
SQL>
select city,product,year,sum(sales)
from tmp1 group by city,CUBE(product,year)
order by city, product, year nulls last;
CITY PRODUCT YEAR SUM(SALES)
北京 冰箱 1999 4000
北京 冰箱 2000 5000
北京 冰箱 2001 6000
北京 冰箱 15000
北京 彩電 1999 1000
北京 彩電 2000 2000
北京 彩電 2001 3000
北京 彩電 6000
北京 1999 5000
北京 2000 7000
北京 2001 9000
北京 21000
天津 冰箱 1999 4100
天津 冰箱 2000 5100
天津 冰箱 2001 6100
天津 冰箱 15300
天津 彩電 1999 1100
天津 彩電 2000 2100
天津 彩電 2001 3100
天津 彩電 6300
天津 1999 5200
天津 2000 7200
天津 2001 9200
天津 21600
- ROLLUP(A, B, C)
#首先会对(A、B、C)进行GROUP BY,
#然后对(A、B)进行GROUP BY,
#然后是(A)进行GROUP BY,
#最后对全表进行GROUP BY操作。
SQL>
select city,product,year,sum(sales)
from tmp1 group by rollup(city,product,year)
order by city, product, year nulls last;
CITY PRODUCT YEAR SUM(SALES)
北京 冰箱 1999 4000
北京 冰箱 2000 5000
北京 冰箱 2001 6000
北京 冰箱 15000
北京 彩電 1999 1000
北京 彩電 2000 2000
北京 彩電 2001 3000
北京 彩電 6000
北京 21000
天津 冰箱 1999 4100
天津 冰箱 2000 5100
天津 冰箱 2001 6100
天津 冰箱 15300
天津 彩電 1999 1100
天津 彩電 2000 2100
天津 彩電 2001 3100
天津 彩電 6300
天津 21600
42600
- A,ROLLUP(B, C)
#首先会对(A、B、C)进行GROUP BY,
#然后对(A、B)进行GROUP BY,
#最后是(A)进行GROUP BY,
SQL>
select city, product,year,sum(sales)
from tmp1 group by city,rollup(product,year)
order by city, product, year nulls last;
CITY PRODUCT YEAR SUM(SALES)
北京 冰箱 1999 4000
北京 冰箱 2000 5000
北京 冰箱 2001 6000
北京 冰箱 15000
北京 彩電 1999 1000
北京 彩電 2000 2000
北京 彩電 2001 3000
北京 彩電 6000
北京 21000
天津 冰箱 1999 4100
天津 冰箱 2000 5100
天津 冰箱 2001 6100
天津 冰箱 15300
天津 彩電 1999 1100
天津 彩電 2000 2100
天津 彩電 2001 3100
天津 彩電 6300
天津 21600