[关闭]
@SovietPower 2022-05-06T16:58:11.000000Z 字数 18166 阅读 1562

数据库系统 实验3 存储过程和触发器

DB



https://opengauss.org/zh/docs/3.0.0/docs/Developerguide/%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84.html

创建函数格式如下。[lang]根据语法可选plpgsqlsql
注意最后还需要一个;结束语句。
如果函数体只需一条语句,则使用sql可删掉declare begin end

  1. create or replace function public.func (arg varchar(20))
  2. returns integer as $$
  3. declare
  4. begin
  5. end;
  6. $$ LANGUAGE [lang];

创建过程。
注意最后还需要一个换行/结束语句。

  1. create or replace procedure public.proc (x in varchar(20), y out integer) as
  2. begin
  3. select count(*) into d_count from instructor
  4. where instructor.dept_name = d_name;
  5. end;
  6. /

函数

运行创建的容器。

  1. PS H:\> docker start opengauss
  2. PS H:\> docker exec -it opengauss bash
  3. root@97375c3acbd1:/# su omm
  4. omm@97375c3acbd1:/$ gsql -d db2022 -r
  5. gsql ((openGauss 2.1.0 build 590b0f8e) compiled at 2021-09-30 14:29:04 commit 0 last mr )
  6. Non-SSL connection (SSL connection is recommended when requiring high-security)
  7. Type "help" for help.
  8. db2022=#

4. 创建dept_count
统计指定院系的教师数量。

  1. db2022=# create or replace function public.dept_count (d_name varchar(20))
  2. db2022-# returns integer
  3. db2022-# LANGUAGE plpgsql
  4. db2022-# as $$
  5. db2022$# declare
  6. db2022$# res integer;
  7. db2022$# begin
  8. db2022$# select count(*) into res from instructor where dept_name=d_name;
  9. db2022$# return res;
  10. db2022$# end; $$;
  11. CREATE FUNCTION

5. 执行dept_count

  1. db2022=# select dept_name, budget
  2. db2022-# from department
  3. db2022-# where dept_count(dept_name)>4;
  4. dept_name | budget
  5. ------------+-----------
  6. Athletics | 734550.70
  7. Statistics | 395051.74
  8. (2 rows)

6. 创建instructor_of
返回指定院系中的所有教师的信息。返回一张表。

  1. db2022=# create or replace function public.instructor_of (d_name varchar(20))
  2. db2022-# returns table(
  3. db2022(# ID varchar(5),
  4. db2022(# name varchar(20),
  5. db2022(# dept_name varchar(20),
  6. db2022(# salary numeric(8,2)
  7. db2022(# )
  8. db2022-# LANGUAGE sql as $$
  9. db2022$# select ID, name, dept_name, salary from instructor
  10. db2022$# where instructor.dept_name=d_name;
  11. db2022$# $$;
  12. CREATE FUNCTION

7. 调用instructor_of

  1. db2022=# select * from instructor_of('Finance');
  2. id | name | dept_name | salary
  3. ------+--------+-----------+-----------
  4. 6569 | Mingoz | Finance | 115311.38
  5. (1 row)

过程

8. 创建dept_count_proc

  1. db2022=# create procedure public.dept_count_proc (d_name in varchar(20), d_count out integer) as
  2. db2022$# begin
  3. db2022$# select count(*) into d_count from instructor
  4. db2022$# where instructor.dept_name = d_name;
  5. db2022$# end;
  6. db2022$# /
  7. CREATE PROCEDURE

9. 调用dept_count_proc

  1. db2022=# call dept_count_proc('Physics', d_count);
  2. d_count
  3. ---------
  4. 2
  5. (1 row)

10. 创建register_student
为学生注册课程。

  1. create or replace procedure public.register_student (
  2. s_id in varchar(5), s_course_id in varchar(8),
  3. s_sec_id in varchar(8), s_semester in varchar(6),
  4. s_year in numeric(4,0), msg out varchar(100)
  5. ) as
  6. declare
  7. enrollment integer;
  8. lim integer;
  9. begin
  10. select count(*) into enrollment from takes
  11. where course_id = s_course_id and sec_id = s_sec_id and semester=s_semester and year=s_year;
  12. select capacity into lim from classroom natural join section
  13. where course_id = s_course_id and sec_id = s_sec_id and semester=s_semester and year=s_year;
  14. if (enrollment < lim) then
  15. begin
  16. insert into takes values(s_id, s_course_id, s_semester, s_year, null);
  17. msg := 'Successful!';
  18. end;
  19. else
  20. msg := 'Enrollment limit reached for course' || s_course_id || ' section' || s_sec_id;
  21. end if;
  22. end;
  23. /
  1. db2022=# create or replace procedure public.register_student (
  2. db2022(# s_id in varchar(5), s_course_id in varchar(8),
  3. db2022(# s_sec_id in varchar(8), s_semester in varchar(6),
  4. db2022(# s_year in numeric(4,0), msg out varchar(100)
  5. db2022(# ) as
  6. db2022$# declare
  7. db2022$# enrollment integer;
  8. db2022$# lim integer;
  9. db2022$# begin
  10. db2022$# select count(*) into enrollment from takes
  11. db2022$# where course_id = s_course_id and sec_id = s_sec_id and semester=s_semester and year=s_year;
  12. db2022$# select capacity into lim from classroom natural join section
  13. db2022$# where course_id = s_course_id and sec_id = s_sec_id and semester=s_semester and year=s_year;
  14. db2022$# if (enrollment < lim) then
  15. db2022$# begin
  16. db2022$# insert into takes values(s_id, s_course_id, s_semester, s_year, null);
  17. db2022$# msg := 'Successful!';
  18. db2022$# end;
  19. db2022$# else
  20. db2022$# msg := 'Enrollment limit reached for course' || s_course_id || ' section' || s_sec_id;
  21. db2022$# end if;
  22. db2022$# end;
  23. db2022$# /
  24. CREATE PROCEDURE

11. 调用register_student

  1. db2022=# call register_student('1018','169','1','Spring','2007',msg);
  2. msg
  3. ------------------------------------------------
  4. Enrollment limit reached for course169 section1
  5. (1 row)
  6. db2022=# call register_student('1018','258','1','Fall','2007',msg);
  7. msg
  8. ------------------------------------------------
  9. Enrollment limit reached for course258 section1
  10. (1 row)

12. 创建test_proc
为该课程在新学期开设一个新的section。该课程所属院系的学生如果之前没有修过该课程,则为其注册该课程。

  1. create or replace procedure public.test_proc (cid in varchar(8), sec in varchar(8), sem varchar(6), y numeric(4,0)) as
  2. declare
  3. dept varchar(20);
  4. cred numeric(2,0);
  5. begin
  6. create temporary table stu(id varchar(5));
  7. insert into section values(cid, sec, sem, y, null, null, null);
  8. select dept_name into dept from course where course_id=cid;
  9. select credits into cred from course where course_id=cid;
  10. insert into stu
  11. (select ID from student where dept_name=dept)
  12. except
  13. (select ID from student natural join takes
  14. where dept_name=dept and course_id=cid);
  15. insert into takes
  16. select ID, cid, sec, sem, y, null
  17. from stu;
  18. update student
  19. set tot_cred = tot_cred+cred
  20. where student.ID in (select ID from stu);
  21. end;
  22. /
  1. db2022=# create or replace procedure public.test_proc (cid in varchar(8), sec in varchar(8), sem varchar(6), y numeric(4,0)) as
  2. db2022$# declare
  3. db2022$# dept varchar(20);
  4. db2022$# cred numeric(2,0);
  5. db2022$# begin
  6. db2022$# create temporary table stu(id varchar(5));
  7. db2022$# insert into section values(cid, sec, sem, y, null, null, null);
  8. db2022$# select dept_name into dept from course where course_id=cid;
  9. db2022$# select credits into cred from course where course_id=cid;
  10. db2022$# insert into stu
  11. db2022$# (select ID from student where dept_name=dept)
  12. db2022$# except
  13. db2022$# (select ID from student natural join takes
  14. db2022$# where dept_name=dept and course_id=cid);
  15. db2022$# insert into takes
  16. db2022$# select ID, cid, sec, sem, y, null
  17. db2022$# from stu;
  18. db2022$# update student
  19. db2022$# set tot_cred = tot_cred+cred
  20. db2022$# where student.ID in (select ID from stu);
  21. db2022$# end;
  22. db2022$# /
  23. CREATE PROCEDURE
  24. db2022=# select * from takes where id='52157';
  25. id | course_id | sec_id | semester | year | grade
  26. -------+-----------+--------+----------+------+-------
  27. ...
  28. 52157 | 747 | 1 | Spring | 2004 | A+
  29. 52157 | 338 | 1 | Spring | 2007 | A-
  30. (18 rows)
  31. db2022=# select * from student where id='52157';
  32. id | name | dept_name | tot_cred
  33. -------+-------+-----------+----------
  34. 52157 | Nagle | Astronomy | 62
  35. (1 row)
  36. db2022=# call test_proc('489', '1', 'Spring', 2022);
  37. test_proc
  38. -----------
  39. (1 row)
  40. db2022=# select * from takes where id='52157';
  41. id | course_id | sec_id | semester | year | grade
  42. -------+-----------+--------+----------+------+-------
  43. ...
  44. 52157 | 747 | 1 | Spring | 2004 | A+
  45. 52157 | 338 | 1 | Spring | 2007 | A-
  46. 52157 | 489 | 1 | Spring | 2022 |
  47. (19 rows)
  48. db2022=# select * from student where id='52157';
  49. id | name | dept_name | tot_cred
  50. -------+-------+-----------+----------
  51. 52157 | Nagle | Astronomy | 66
  52. (1 row)

触发器

与其它数据库管理系统不同,openGauss在创建触发器时并不直接包含所执行的处理逻辑,而是将处理逻辑放在事先创建的不
带参数且返回类型为TRIGGER的函数中,在触发器的定义中指定调用该函数。
openGauss不支持函数中使用COMMIT/ROLLBACK/SAVEPOINT(包括函数调用含有COMMIT/ROLLBACK/SAVEPOINT的存储过程)。
openGauss不支持TRIGGER中调用含有COMMIT/ROLLBACK/SAVEPOINT语句的存储过程。

13. 为触发器创建函数 tri_insert_section_func 和 tri_delete_timeslot_func

  1. create or replace function public.tri_insert_section_func ()
  2. returns trigger
  3. not fenced not shippable as $$
  4. declare
  5. begin
  6. if new.time_slot_id not in (select time_slot_id from time_slot) then
  7. delete from section
  8. where course_id=new.course_id and sec_id=new.sec_id and semester=new.semester and year=new.year;
  9. raise exception 'time_slot table中不存在指定的time_slot_it,insert失败.';
  10. end if;
  11. return new;
  12. end;
  13. $$ LANGUAGE plpgsql;
  14. create or replace function public.tri_delete_timeslot_func ()
  15. returns trigger
  16. not fenced not shippable as $$
  17. declare
  18. begin
  19. if old.time_slot_id not in (select time_slot_id from time_slot) and old.time_slot_id in (select time_slot_id from section) then
  20. insert into time_slot values(old.time_slot_id, old.day, old.start_hr, old.start_min, old.end_hr, old.end_min);
  21. raise exception 'time_slot_id仍被section引用,delete失败.';
  22. end if;
  23. return old;
  24. end;
  25. $$ LANGUAGE plpgsql;
  1. db2022=# create or replace function public.tri_insert_section_func ()
  2. db2022-# returns trigger
  3. db2022-# not fenced not shippable as $$
  4. db2022$# declare
  5. db2022$#
  6. db2022$# begin
  7. db2022$# if new.time_slot_id not in (select time_slot_id from time_slot) then
  8. db2022$# delete from section
  9. db2022$# where course_id=new.course_id and sec_id=new.sec_id and semester=new.semester and year=new.year;
  10. db2022$# raise exception 'time_slot table中不存在指定的time_slot_it,insert失败.';
  11. db2022$# end if;
  12. db2022$# return new;
  13. db2022$# end;
  14. db2022$# $$ LANGUAGE plpgsql;
  15. CREATE FUNCTION
  16. db2022=# create or replace function public.tri_delete_timeslot_func ()
  17. db2022-# returns trigger
  18. db2022-# not fenced not shippable as $$
  19. db2022$# declare
  20. db2022$#
  21. db2022$# begin
  22. db2022$# if old.time_slot_id not in (select time_slot_id from time_slot) and old.time_slot_id in (select time_slot_id from section) then
  23. db2022$# insert into time_slot values(old.time_slot_id, old.day, old.start_hr, old.start_min, old.end_hr, old.end_min);
  24. db2022$# raise exception 'time_slot_id仍被section引用,delete失败.';
  25. db2022$# end if;
  26. db2022$# return old;
  27. db2022$# end;
  28. db2022$# $$ LANGUAGE plpgsql;
  29. CREATE FUNCTION

14. 创建触发器 insert_section_timeslot_check 和 delete_timeslot_check

  1. db2022=# create trigger insert_section_timeslot_check after insert on section
  2. db2022-# for each row
  3. db2022-# execute procedure tri_insert_section_func();
  4. CREATE TRIGGER
  5. db2022=# create trigger delete_timeslot_check after delete on time_slot
  6. db2022-# for each row
  7. db2022-# execute procedure tri_delete_timeslot_func();
  8. CREATE TRIGGER

15. 检查触发器 insert_section_timeslot_check 效果

  1. db2022=# select * from time_slot where time_slot_id = 'Q';
  2. time_slot_id | day | start_hr | start_min | end_hr | end_min
  3. --------------+-----+----------+-----------+--------+---------
  4. (0 rows)
  5. db2022=# insert into section values('747','1','Fall',2021,'Gates','314','Q');
  6. ERROR: time_slot table中不存在指定的time_slot_itinsert失败.
  7. db2022=# select * from section where course_id = '747' and sec_id = '1' and semester = 'Fall' and year = 2021;
  8. course_id | sec_id | semester | year | building | room_number | time_slot_id
  9. -----------+--------+----------+------+----------+-------------+--------------
  10. (0 rows)
  11. db2022=# insert into time_slot values('Q','W',10,0,12,30);
  12. INSERT 0 1
  13. db2022=# insert into section values('747','1','Fall',2021,'Gates','314','Q');
  14. INSERT 0 1
  15. db2022=# select * from section where course_id = '747' and sec_id = '1' and semester = 'Fall' and year = 2021;
  16. course_id | sec_id | semester | year | building | room_number | time_slot_id
  17. -----------+--------+----------+------+----------+-------------+--------------
  18. 747 | 1 | Fall | 2021 | Gates | 314 | Q
  19. (1 row)

16. 检查触发器 delete_timeslot_check 效果

  1. db2022=# insert into time_slot values('Q','F',10,0,12,30);
  2. INSERT 0 1
  3. db2022=# select * from time_slot where time_slot_id = 'Q';
  4. time_slot_id | day | start_hr | start_min | end_hr | end_min
  5. --------------+-----+----------+-----------+--------+---------
  6. Q | W | 10 | 0 | 12 | 30
  7. Q | F | 10 | 0 | 12 | 30
  8. (2 rows)
  9. db2022=# delete from time_slot where time_slot_id = 'Q' and day = 'W';
  10. DELETE 1
  11. db2022=# select * from time_slot where time_slot_id = 'Q';
  12. time_slot_id | day | start_hr | start_min | end_hr | end_min
  13. --------------+-----+----------+-----------+--------+---------
  14. Q | F | 10 | 0 | 12 | 30
  15. (1 row)
  16. db2022=# delete from time_slot where time_slot_id = 'Q' and day = 'F';
  17. ERROR: time_slot_id仍被section引用,delete失败.
  18. db2022=# select * from time_slot where time_slot_id = 'Q';
  19. time_slot_id | day | start_hr | start_min | end_hr | end_min
  20. --------------+-----+----------+-----------+--------+---------
  21. Q | F | 10 | 0 | 12 | 30
  22. (1 row)
  23. db2022=# select * from section where time_slot_id = 'Q';
  24. course_id | sec_id | semester | year | building | room_number | time_slot_id
  25. -----------+--------+----------+------+----------+-------------+--------------
  26. 747 | 1 | Fall | 2021 | Gates | 314 | Q
  27. (1 row)
  28. db2022=# delete from section where time_slot_id = 'Q';
  29. DELETE 1
  30. db2022=# delete from time_slot where time_slot_id = 'Q' and day = 'F';
  31. DELETE 1
  32. db2022=# select * from time_slot where time_slot_id = 'Q';
  33. time_slot_id | day | start_hr | start_min | end_hr | end_min
  34. --------------+-----+----------+-----------+--------+---------
  35. (0 rows)

17. 删除创建的触发器和函数

  1. db2022=# DROP TRIGGER delete_timeslot_check on time_slot;
  2. DROP TRIGGER
  3. db2022=# DROP TRIGGER insert_section_timeslot_check on section;
  4. DROP TRIGGER
  5. db2022=# DROP FUNCTION IF EXISTS tri_insert_section_func;
  6. DROP FUNCTION
  7. db2022=# DROP FUNCTION IF EXISTS tri_delete_timeslot_func;
  8. DROP FUNCTION

18. 创建触发器 tri_update_credits
用于维护学生所获得的学分。

  1. create or replace function public.on_update_credits_func ()
  2. returns trigger
  3. not fenced not shippable as $$
  4. begin
  5. if new.grade<>'F' and new.grade is not null and (old.grade='F' or old.grade is null) then
  6. update student
  7. set tot_cred = tot_cred+
  8. (select credits from course where course.course_id=new.course_id);
  9. end if;
  10. return new;
  11. end;
  12. $$ LANGUAGE plpgsql;
  13. create trigger on_update_credits after update on takes
  14. for each row
  15. execute procedure on_update_credits_func();
  1. db2022=# create or replace function public.on_update_credits_func ()
  2. db2022-# returns trigger
  3. db2022-# not fenced not shippable as $$
  4. db2022$# begin
  5. db2022$# if new.grade<>'F' and new.grade is not null and (old.grade='F' or old.grade is null) then
  6. db2022$# update student
  7. db2022$# set tot_cred = tot_cred+
  8. db2022$# (select credits from course where course.course_id=new.course_id);
  9. db2022$# end if;
  10. db2022$# return new;
  11. db2022$# end;
  12. db2022$# $$ LANGUAGE plpgsql;
  13. CREATE FUNCTION
  14. db2022=# create trigger on_update_credits after update on takes
  15. db2022-# for each row
  16. db2022-# execute procedure on_update_credits_func();
  17. CREATE TRIGGER
  18. db2022=# select * from takes where grade='F';
  19. id | course_id | sec_id | semester | year | grade
  20. -------+-----------+--------+----------+------+-------
  21. 79446 | 808 | 1 | Fall | 2003 | F
  22. 99710 | 169 | 2 | Fall | 2002 | F
  23. ...
  24. db2022=# select * from student where id='99710';
  25. id | name | dept_name | tot_cred
  26. -------+------------+-----------+----------
  27. 99710 | Savolainen | Languages | 50
  28. (1 row)
  29. db2022=# update takes set grade='A' where id='99710' and course_id='169' and sec_id='2';
  30. UPDATE 1
  31. db2022=# select * from student where id='99710';
  32. id | name | dept_name | tot_cred
  33. -------+------------+-----------+----------
  34. 99710 | Savolainen | Languages | 53
  35. (1 row)

递归

19. 创建视图 rec_prereq
找出所有课程的直接和间接前导课程。

  1. db2022=# create view rec_prereq as
  2. db2022-# with recursive rec_prereq(course_id, prereq_id) as (
  3. db2022(# select course_id, prereq_id
  4. db2022(# from prereq
  5. db2022(# union
  6. db2022(# select rec_prereq.course_id, prereq.prereq_id
  7. db2022(# from rec_prereq, prereq
  8. db2022(# where rec_prereq.prereq_id = prereq.course_id
  9. db2022(# )
  10. db2022-# select * from rec_prereq;
  11. CREATE VIEW
  12. db2022=# select * from rec_prereq where course_id='760';
  13. course_id | prereq_id
  14. -----------+-----------
  15. 760 | 169
  16. 760 | 603
  17. 760 | 735
  18. (3 rows)

高级聚集函数

20. 创建视图 students_gpa
显示学生的GPA。

  1. db2022=# create view students_gpa as
  2. db2022-# select id, name, round(sum(point*credits)/sum(credits), 1) as GPA
  3. db2022-# from student natural left outer join (
  4. db2022(# select id, takes.course_id, course.credits, max(point) as point
  5. db2022(# from takes, grade_point, course
  6. db2022(# where trim(takes.grade) = grade_point.grade and takes.course_id = course.course_id
  7. db2022(# group by id, takes.course_id, course.credits
  8. db2022(# ) group by id, name;
  9. CREATE VIEW
  10. db2022=# select * from students_gpa where name='Cox';
  11. id | name | gpa
  12. -------+------+-----
  13. 59908 | Cox | 2.8
  14. 21766 | Cox | 3.0
  15. 44304 | Cox | 3.4
  16. (3 rows)

21. 查询学生的GPA排名

  1. db2022=# select ID, name, gpa, rank() over (order by (GPA) desc) as s_rank
  2. db2022-# from students_gpa
  3. db2022-# limit 5;
  4. id | name | gpa | s_rank
  5. -------+---------+-----+--------
  6. 79446 | Frost | | 1
  7. 56499 | Zarpell | 3.9 | 2
  8. 81896 | Feldman | 3.9 | 2
  9. 18286 | Pang | 3.9 | 2
  10. 98619 | Nagaraj | 3.9 | 2
  11. (5 rows)
  12. db2022=# select ID, name, rank() over (order by GPA desc nulls last) as s_rank
  13. db2022-# from students_gpa
  14. db2022-# limit 5;
  15. id | name | s_rank
  16. -------+---------+--------
  17. 98619 | Nagaraj | 1
  18. 18286 | Pang | 1
  19. 56499 | Zarpell | 1
  20. 81896 | Feldman | 1
  21. 4248 | Wright | 5
  22. (5 rows)
  23. db2022=# select ID, (1 + (select count(*) from students_gpa B where B.GPA > A.GPA)) as s_rank
  24. db2022-# from students_gpa A
  25. db2022-# order by s_rank
  26. db2022-# limit 5;
  27. id | s_rank
  28. -------+--------
  29. 81896 | 1
  30. 79446 | 1
  31. 18286 | 1
  32. 98619 | 1
  33. 56499 | 1
  34. (5 rows)

22. 创建视图 dept_grades
显示学生的GPA,包含其院系。

  1. db2022=# create view dept_grades as
  2. db2022-# select id, name, dept_name, round(sum(point*credits)/sum(credits), 1) as GPA
  3. db2022-# from student natural left outer join (
  4. db2022(# select id, takes.course_id, course.credits, max(point) as point
  5. db2022(# from takes, grade_point, course
  6. db2022(# where trim(takes.grade) = grade_point.grade and takes.course_id = course.course_id
  7. db2022(# group by id, takes.course_id, course.credits
  8. db2022(# ) group by id, name;
  9. CREATE VIEW
  10. db2022=# select * from dept_grades;
  11. id | name | dept_name | gpa
  12. -------+--------------------+-------------+-----
  13. 92776 | Oki | Psychology | 2.4
  14. 94894 | Kozlov | Accounting | 2.7
  15. 26881 | Markin | History | 3.0
  16. ...

23. 按院系查询学生的GPA排名

  1. db2022=# select ID, dept_name, gpa,
  2. db2022-# rank () over (partition by dept_name order by GPA desc) as dept_rank
  3. db2022-# from dept_grades
  4. db2022-# order by dept_name, dept_rank
  5. db2022-# limit 3;
  6. id | dept_name | gpa | dept_rank
  7. -------+------------+-----+-----------
  8. 69679 | Accounting | 3.8 | 1
  9. 14829 | Accounting | 3.5 | 2
  10. 23457 | Accounting | 3.5 | 2
  11. (3 rows)

24. 创建视图 tot_credits
统计所有学生每年所获得的总学分。

  1. db2022=# create view tot_credits(year,credits) as
  2. db2022-# with temp1(year, credits) as
  3. db2022-# (select year, sum(credits) from takes natural join course
  4. db2022(# where grade <> 'F' or grade is not null
  5. db2022(# group by year),
  6. db2022-# temp2(year, credits) as
  7. db2022-# (select 2001,0 union select 2002,0 union
  8. db2022(# select 2003,0 union select 2004,0 union
  9. db2022(# select 2005,0 union select 2006,0 union
  10. db2022(# select 2007,0 union select 2008,0 union
  11. db2022(# select 2009,0 union select 2010,0 union
  12. db2022(# select 2011,0 union select 2012,0 union
  13. db2022(# select 2013,0 union select 2014,0 union
  14. db2022(# select 2015,0 union select 2016,0 union
  15. db2022(# select 2017,0 union select 2018,0 union
  16. db2022(# select 2019,0 union select 2020,0 union
  17. db2022(# select 2021,0 union select 2022,0)
  18. db2022-# select * from temp1
  19. db2022-# UNION
  20. db2022-# select * from temp2 where year not in (select year from temp1);
  21. CREATE VIEW
  22. db2022=# select * from tot_credits limit 3;
  23. year | credits
  24. ------+---------
  25. 2012 | 0
  26. 2004 | 7085
  27. 2018 | 0
  28. (3 rows)

25. 使用窗口函数查询不同条件下所有学生所获得的平均学分

  1. db2022=# select year, round(avg(credits) over (order by year rows 3 preceding), 2)
  2. db2022-# as avg_total_credits
  3. db2022-# from tot_credits
  4. db2022-# limit 3;
  5. year | avg_total_credits
  6. ------+-------------------
  7. 2001 | 4530.00
  8. 2002 | 8984.00
  9. 2003 | 10307.00
  10. (3 rows)
  11. db2022=# select year, round(avg(credits) over (order by year rows unbounded preceding), 2)
  12. db2022-# as avg_total_credits
  13. db2022-# from tot_credits
  14. db2022-# limit 3;
  15. year | avg_total_credits
  16. ------+-------------------
  17. 2001 | 4530.00
  18. 2002 | 8984.00
  19. 2003 | 10307.00
  20. (3 rows)
  21. db2022=# select year, round(avg(credits) over (order by year rows between 3 preceding and 2 following), 2)
  22. db2022-# as avg_total_credits
  23. db2022-# from tot_credits
  24. db2022-# limit 3;
  25. year | avg_total_credits
  26. ------+-------------------
  27. 2001 | 10307.00
  28. 2002 | 9501.50
  29. 2003 | 9362.20
  30. (3 rows)

26. 创建视图 student_tot_credits(id, year, credits)
统计每个学生每年所获得的总学分。

  1. db2022=# create view student_tot_credits as
  2. db2022-# select ID, year, sum(course.credits) as credits
  3. db2022-# from takes natural join course
  4. db2022-# group by ID, year;
  5. CREATE VIEW
  6. db2022=# select * from student_tot_credits limit 3;
  7. id | year | credits
  8. -------+------+---------
  9. 108 | 2006 | 4
  10. 58874 | 2007 | 4
  11. 22618 | 2002 | 3
  12. (3 rows)

27. 查询每个学生连续三年所获得的平均学分数

  1. select ID, year, round(avg(credits)
  2. over (partition by ID order by year rows 3 preceding), 2)
  3. from student_tot_credits;
  1. db2022=# select * from student_tot_credits where id='108';
  2. id | year | credits
  3. -----+------+---------
  4. 108 | 2006 | 4
  5. 108 | 2010 | 7
  6. 108 | 2004 | 4
  7. 108 | 2001 | 3
  8. 108 | 2008 | 11
  9. 108 | 2002 | 10
  10. 108 | 2007 | 10
  11. 108 | 2003 | 7
  12. (8 rows)
  13. db2022=# select ID, year, round(avg(credits)
  14. db2022(# over (partition by ID order by year rows 3 preceding), 2)
  15. db2022-# from student_tot_credits where id='108';
  16. id | year | round
  17. -----+------+-------
  18. 108 | 2001 | 3.00
  19. 108 | 2002 | 6.50
  20. 108 | 2003 | 6.67
  21. 108 | 2004 | 6.00
  22. 108 | 2006 | 6.25
  23. 108 | 2007 | 6.25
  24. 108 | 2008 | 7.25
  25. 108 | 2010 | 8.00
  26. (8 rows)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注