Oracle开发者中级第4课(分析函数)实验
Posted dingdingfish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle开发者中级第4课(分析函数)实验相关的知识,希望对你有一定的参考价值。
概述
本实验参考DevGym中的实验指南。
创建环境
首先创建表:
create table bricks (
brick_id integer,
colour varchar2(10),
shape varchar2(10),
weight integer
);
insert into bricks values ( 1, 'blue', 'cube', 1 );
insert into bricks values ( 2, 'blue', 'pyramid', 2 );
insert into bricks values ( 3, 'red', 'cube', 1 );
insert into bricks values ( 4, 'red', 'cube', 2 );
insert into bricks values ( 5, 'red', 'pyramid', 3 );
insert into bricks values ( 6, 'green', 'pyramid', 1 );
commit;
查看数据:
SQL> select * from bricks;
BRICK_ID COLOUR SHAPE WEIGHT
___________ _________ __________ _________
1 blue cube 1
2 blue pyramid 2
3 red cube 1
4 red cube 2
5 red pyramid 3
6 green pyramid 1
6 rows selected.
聚合和分析函数的区别
第一个是聚合(多行到1行),后续两个是分析函数(使用了over,仍保留多行)。
SQL> select count(*) from bricks;
COUNT(*)
___________
6
SQL> select count(*) over () from bricks;
COUNT(*)OVER()
_________________
6
6
6
6
6
6
6 rows selected.
SQL> select b.*,
2 count(*) over () total_count
3 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT TOTAL_COUNT
___________ _________ __________ _________ ______________
1 blue cube 1 6
2 blue pyramid 2 6
3 red cube 1 6
4 red cube 2 6
5 red pyramid 3 6
6 green pyramid 1 6
6 rows selected.
Partition By
以下SQL展示了Group By和Partition By的区别。实际上也就是聚合与分析函数的区别。
SQL> select colour, count(*), sum ( weight )
2 from bricks
3 group by colour;
COLOUR COUNT(*) SUM(WEIGHT)
_________ ___________ ______________
red 3 6
green 1 1
blue 2 3
SQL> select b.*,
2 count(*) over (
3 partition by colour
4 ) bricks_per_colour,
5 sum ( weight ) over (
6 partition by colour
7 ) weight_per_colour
8 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT BRICKS_PER_COLOUR WEIGHT_PER_COLOUR
___________ _________ __________ _________ ____________________ ____________________
2 blue pyramid 2 2 3
1 blue cube 1 2 3
6 green pyramid 1 1 1
5 red pyramid 3 3 6
4 red cube 2 3 6
3 red cube 1 3 6
6 rows selected.
练习的答案如下:
select b.*,
count(*) over (
partition by shape
) bricks_per_shape,
median ( weight ) over (
partition by shape
) median_weight_per_shape
from bricks b
order by shape, weight, brick_id;
Order By
over加order by可实现实时合计(running totals),例如:
SQL> select b.*,
2 count(*) over (
3 order by brick_id
4 ) running_total,
5 sum ( weight ) over (
6 order by brick_id
7 ) running_weight
8 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT RUNNING_TOTAL RUNNING_WEIGHT
___________ _________ __________ _________ ________________ _________________
1 blue cube 1 1 1
2 blue pyramid 2 2 3
3 red cube 1 3 4
4 red cube 2 4 6
5 red pyramid 3 5 9
6 green pyramid 1 6 10
6 rows selected.
Partition By + Order By
两者结合可实现partition内的实时合计(running totals):
SQL>
select b.*,
count(*) over (
partition by colour
order by brick_id
) running_total,
sum ( weight ) over (
partition by colour
order by brick_id
) running_weight
from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT RUNNING_TOTAL RUNNING_WEIGHT
___________ _________ __________ _________ ________________ _________________
1 blue cube 1 1 1
2 blue pyramid 2 2 3
6 green pyramid 1 1 1
3 red cube 1 1 1
4 red cube 2 2 3
5 red pyramid 3 3 6
6 rows selected.
Windowing子句
当over + order by结合时,数据库添加了以下默认的Windowing子句,即包括值小于或等于当前行的所有行。:
range between unbounded preceding and current row
所以在下例中,weight相同的行,RUNNING_TOTAL和RUNNING_WEIGHT也是相同的:
SQL> select b.*,
2 count(*) over (
3 order by weight
4 ) running_total,
5 sum ( weight ) over (
6 order by weight
7 ) running_weight
8 from bricks b
9 order by weight;
BRICK_ID COLOUR SHAPE WEIGHT RUNNING_TOTAL RUNNING_WEIGHT
___________ _________ __________ _________ ________________ _________________
1 blue cube 1 3 3
3 red cube 1 3 3
6 green pyramid 1 3 3
4 red cube 2 5 7
2 blue pyramid 2 5 7
5 red pyramid 3 6 10
6 rows selected.
窗口是可以调整的,以下SQL将默认的range替换为rows:
SQL> select b.*,
2 count(*) over (
3 order by weight
4 rows between unbounded preceding and current row
5 ) running_total,
6 sum ( weight ) over (
7 order by weight
8 rows between unbounded preceding and current row
9 ) running_weight
10 from bricks b
11 order by weight;
BRICK_ID COLOUR SHAPE WEIGHT RUNNING_TOTAL RUNNING_WEIGHT
___________ _________ __________ _________ ________________ _________________
1 blue cube 1 1 1
3 red cube 1 2 2
6 green pyramid 1 3 3
4 red cube 2 4 5
2 blue pyramid 2 5 7
5 red pyramid 3 6 10
6 rows selected.
由于weight有相同的,为避免出现tie的现象,还需要多添加一个order by brick_id,使结果集顺序固定,或者也可以说,使结果集唯一:
select b.*,
count(*) over (
order by weight, brick_id
rows between unbounded preceding and current row
) running_total,
sum ( weight ) over (
order by weight, brick_id
rows between unbounded preceding and current row
) running_weight
from bricks b
order by weight, brick_id;
滑动窗口(Sliding Windows)
看3个例子:
SQL> select b.*,
2 sum ( weight ) over (
3 order by weight
4 rows between 1 preceding and current row
5 ) running_row_weight,
6 sum ( weight ) over (
7 order by weight
8 range between 1 preceding and current row
9 ) running_value_weight
10 from bricks b
11 order by weight, brick_id;
BRICK_ID COLOUR SHAPE WEIGHT RUNNING_ROW_WEIGHT RUNNING_VALUE_WEIGHT
___________ _________ __________ _________ _____________________ _______________________
1 blue cube 1 1 3
3 red cube 1 2 3
6 green pyramid 1 2 3
2 blue pyramid 2 3 7
4 red cube 2 4 7
5 red pyramid 3 5 7
6 rows selected.
SQL> select b.*,
2 sum ( weight ) over (
3 order by weight
4 rows between 1 preceding and 1 following
5 ) sliding_row_window,
6 sum ( weight ) over (
7 order by weight
8 range between 1 preceding and 1 following
9 ) sliding_value_window
10 from bricks b
11 order by weight;
BRICK_ID COLOUR SHAPE WEIGHT SLIDING_ROW_WINDOW SLIDING_VALUE_WINDOW
___________ _________ __________ _________ _____________________ _______________________
1 blue cube 1 2 7
3 red cube 1 3 7
6 green pyramid 1 4 7
4 red cube 2 5 10
2 blue pyramid 2 7 10
5 red pyramid 3 5 7
6 rows selected.
SQL> select b.*,
2 count (*) over (
3 order by weight
4 range between 2 preceding and 1 preceding
5 ) count_weight_2_lower_than_current,
6 count (*) over (
7 order by weight
8 range between 1 following and 2 following
9 ) count_weight_2_greater_than_current
10 from bricks b
11 order by weight;
BRICK_ID COLOUR SHAPE WEIGHT COUNT_WEIGHT_2_LOWER_THAN_CURRENT COUNT_WEIGHT_2_GREATER_THAN_CURRENT
___________ _________ __________ _________ ____________________________________ ______________________________________
1 blue cube 1 0 3
3 red cube 1 0 3
6 green pyramid 1 0 3
4 red cube 2 3 1
2 blue pyramid 2 3 1
5 red pyramid 3 5 0
6 rows selected.
分析函数的过滤
结合函数的过滤用having:
SQL> select colour from bricks
2 group by colour
3 having count(*) >= 2;
COLOUR
_________
red
blue
由于数据库处理where条件在前,分析函数在后。因此分析函数的过滤仍需结合子查询:
SQL> select b.*,
2 count(*) over ( partition by colour ) colour_count
3 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT COLOUR_COUNT
___________ _________ __________ _________ _______________
2 blue pyramid 2 2
1 blue cube 1 2
6 green pyramid 1 1
5 red pyramid 3 3
4 red cube 2 3
3 red cube 1 3
6 rows selected.
SQL> select * from (
2 select b.*,
3 count(*) over ( partition by colour ) colour_count
4 from bricks b
5 )
6 where colour_count >= 2;
BRICK_ID COLOUR SHAPE WEIGHT COLOUR_COUNT
___________ _________ __________ _________ _______________
2 blue pyramid 2 2
1 blue cube 1 2
5 red pyramid 3 3
4 red cube 2 3
3 red cube 1 3
更多分析函数
包括row_number,rank,dense_rank,lag,lead,first_value,last_value
-- row_number,rank,dense_rank示例
SQL> select brick_id, weight,
2 row_number() over ( order by weight ) rn,
3 rank() over ( order by weight ) rk,
4 dense_rank() over ( order by weight ) dr
5 from bricks;
BRICK_ID WEIGHT RN RK DR
___________ _________ _____ _____ _____
1 1 1 1 1
3 1 2 1 1
6 1 3 1 1
4 2 4 4 2
2 2 5 4 2
5 3 6 6 3
6 rows selected.
-- lag,lead示例,即前一个值和后一个值
SQL> select b.*,
2 lag ( shape ) over ( order by brick_id ) prev_shape,
3 lead ( shape ) over ( order by brick_id ) next_shape
4 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT PREV_SHAPE NEXT_SHAPE
___________ _________ __________ _________ _____________ _____________
1 blue cube 1 pyramid
2 blue pyramid 2 cube cube
3 red cube 1 pyramid cube
4 red cube 2 cube pyramid
5 red pyramid 3 cube pyramid
6 green pyramid 1 pyramid
6 rows selected.
-- first_value,last_value示例。排序集合中的第一个和最后一个值。注意以下2个示例的区别,和窗口有关。
SQL> select b.*,
2 first_value ( weight ) over (
3 order by brick_id
4 ) first_weight_by_id,
5 last_value ( weight ) over (
6 order by brick_id
7 ) last_weight_by_id
8 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT FIRST_WEIGHT_BY_ID LAST_WEIGHT_BY_ID
___________ _________ __________ _________ _____________________ ____________________
1 blue cube 1 1 1
2 blue pyramid 2 1 2
3 red cube 1 1 1
4 red cube 2 1 2
5 red pyramid 3 1 3
6 green pyramid 1 1 1
6 rows selected.
SQL> select b.*,
2 first_value ( weight ) over (
3 order by brick_id
4 ) first_weight_by_id,
5 last_value ( weight ) over (
6 order by brick_id
7 range between current row and unbounded following
8 ) last_weight_by_id
9 from bricks b;
BRICK_ID COLOUR SHAPE WEIGHT FIRST_WEIGHT_BY_ID LAST_WEIGHT_BY_ID
___________ _________ __________ _________ _____________________ ____________________
1 blue cube 1 1 1
2 blue pyramid 2 1 1
3 red cube 1 1 1
4 red cube 2 1 1
5 red pyramid 3 1 1
6 green pyramid 1 1 1
6 rows selected.
以上是关于Oracle开发者中级第4课(分析函数)实验的主要内容,如果未能解决你的问题,请参考以下文章