• 数据库实践 Hw08


    1

    查询每个银行内的存款总额(不包括贷款、保险)、所有贷款的总额、存款最多的存款金额、贷款总额与存款总额之比;
    输出:branch_id,存款总额,贷款总额,存款最多的存款金额,贷款总额:存款总额
    示例:
    ±---------------±---------------±-------------±--------------±-----------+
    | OPEN_BRANCH_ID | saving | loans | maxs | precent |
    ±---------------±---------------±-------------±--------------±-----------+
    | 2 | 231201772.6167 | 0.0000 | 99021770.1967 | 0.00000000 |
    ±---------------±---------------±-------------±--------------±-----------+

    注:该示例不是标准答案

    SELECT t.*, t.loans/t.saving as ratio from(
    SELECT a.OPEN_BRANCH_ID,sum(if(pp.name='存款',a.AVAIL_BALANCE,0)) as deposits,
    sum(if(pp.name='贷款',a.AVAIL_BALANCE,0)) as loans,
    max(if(pp.name='存款',a.AVAIL_BALANCE,0)) as max_deposit
    from account a 
    JOIN PRODUCT p on p.PRODUCT_CD = a.PRODUCT_CD 
    join product_type pp on pp.product_type_cd=p.product_type_cd
    GROUP BY OPEN_BRANCH_ID
    ) as t 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    
    select branch_id, saving, maxs, coalesce(loan, 0) loan, ( ifnull(sec.loan, 0) / fir.saving) as percent from 
    (
    	(select BRANCH_ID, sum(avail_balance) saving, max(avail_balance) maxs
    	from (branch b, account a, product p) 
    	where b.branch_id = a.open_branch_id
    	and a.product_cd = p.product_cd
    	and p.product_type_cd = 'ACCOUNT'
    	group by BRANCH_ID) as fir
    left outer join 
    	(
    	select BRANCH_ID, IFNULL(sum(avail_balance), 0) loan
    	from (branch b, account a, product p) 
    	where b.branch_id = a.open_branch_id
    	and a.product_cd = p.product_cd
    	and p.product_type_cd = 'LOAN'
    	group by BRANCH_ID
    	) as sec
    using(branch_id)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2

    请使用with rescusive 递归查询每个员工的上级领导。输出员工id、上级领导|该员工ID。
    答案示例:
    ±-------±------------+
    | emp_id | res |
    ±-------±------------+
    | 1 | 1 |
    | 2 | 1|2 |
    | 3 | 1|3 |
    | 20 | 1|2|20 |
    | 4 | 1|3|4 |
    ±-------±------------+

    注:示例是标准答案部分数据

    with recursive t(emp_id,res) as( 
    (select emp_id ,cast(emp_id as char ) from employee where superior_emp_id is null  )
    union all (select e.emp_id,CONCAT(t.res,'|',e.emp_id)as res from t,employee  e where t.emp_id = e.superior_emp_id  )) 
    select * from t;
    
    • 1
    • 2
    • 3
    • 4
    select * from employee;
    select emp_id, cast(coalesce(concat(superior_emp_id, '|', emp_id), emp_id) as char(30)) as res
        from employee;
    WITH recursive cte(emp_id, res) as
    (
    	select e.emp_id , coalesce(concat(superior_emp_id, '|', emp_id), emp_id) as res
        from employee e
        where e.superior_emp_id is NULL
        union
        select e.emp_id , concat(res, '|', e.emp_id) 
        from employee e inner join cte
        where e.superior_emp_id = cte.emp_id
    )
    select * from cte;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3

    利用游标修改account表的AVAIL_BALANCE;如果该金额是属于存款,则按利息每年利息0.00001增加,以last_activity_date开始计算。
    注:先更新一下account表
    update account set last_activity_date=‘2022-11-11’ where last_activity_date is null;
    提示:使用函数 timestampdiff

    CREATE DEFINER = `root` @`localhost` PROCEDURE `proc_cursor2` () DETERMINISTIC BEGIN
    DECLARE done INT DEFAULT ( 0 );
    DECLARE accountid INT;
    DECLARE  n INT;
    DECLARE  i INT;
    DECLARE ans DECIMAL ( 12, 4 );
    
    DECLARE cur_1 CURSOR FOR SELECT
    ACCOUNT_ID ,AVAIL_BALANCE FROM account;
    
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' 
    SET done = 1;
    
    OPEN cur_1;
    
    REPEAT
    	set i = 0;
    	FETCH cur_1 INTO accountid,ans;
    	
    	SELECT timestampdiff(YEAR,last_activity_date,now()) into n
    	FROM account  WHERE ACCOUNT_ID = accountid;
    	
    	WHILE i < n DO
    		set ans = ans * 0.00001;
    		set i = i+1;
    	END WHILE;
    	
    	UPDATE account 
    	SET AVAIL_BALANCE = ans 
    	WHERE
    	account.ACCOUNT_ID = accountid;
    	UNTIL done 
    END REPEAT;
    CLOSE cur_1;
    END 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    SET SQL_SAFE_UPDATES = 0;
    update account set last_activity_date='2022-11-11' where last_activity_date is null;
    
    select * from account;
    update account set avail_balance = 10000 where avail_balance is null;
    desc account;
    
    
    drop procedure  if exists updateAB;
    delimiter $$
    create procedure updateAB()
    begin
    	declare ai int;
    	declare ab decimal(12, 4);
        declare lad date;
        declare dif int;
    	
        declare cur cursor for
    		select account_id, avail_balance, last_activity_date
            from account;
    	DECLARE exit HANDLER FOR NOT FOUND CLOSE cur;
        
        open cur;
        repeat 
    		fetch cur into ai, ab, lad;
    		set dif = timestampdiff(year, lad, NOW());
            
    			while(dif > 0) do
    				set ab = ab * 1.00001;
    				set dif = dif - 1;
    			end while;
    	-- select dif;
             update account set avail_balance = ab
             where account_id = ai;
        until null 
        end repeat;
        close cur;
    end $$
    delimiter ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    4

    4
    新建日志表

    CREATE TABLE `logs` (
     `Id` int(11) NOT NULL AUTO_INCREMENT,
     `log` varchar(255) DEFAULT NULL COMMENT '日志说明',
     PRIMARY KEY (`Id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志表';
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在players表(第七次作业中已建好的表)中新建update触发器

    1. 更新了players表数据就要添加一条日志数据信息。如果有数据被更改,则在logs表中增加一条元组,具体格式为:“列名” + “该列旧数据” + “ is updated to ” + “该列新数据;”;如果该列没有被更新,则无需添加说明。
      注:每一次触发只能有增加一条元组。
    2. 如果某个player转会,其team_id会做相应更改,在team表中的nums(球队人数)也要需要更新。

    写好触发器后,请依次运行如下SQL语句,检查触发器运行结果:

     SELECT * from teams;
     UPDATE players set salary = 10*salary,team_id=3 WHERE `name`="姚明";
     SELECT * from teams;
     SELECT * from logs;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    DROP TRIGGER IF EXISTS `player_log`;
    delimiter;;
    CREATE TRIGGER `player_log` AFTER UPDATE ON `players` FOR EACH ROW
    BEGIN 
    DECLARE s1 VARCHAR ( 1000 ) CHARACTER 
    SET utf8;
    DECLARE
    	s2 VARCHAR ( 20 ) CHARACTER 
    	SET utf8;# 为避免中文字符编码出现乱码,这里需要设置字符集
    DECLARE
    	res VARCHAR ( 40 ) CHARACTER 
    	SET utf8;
    SET s2 = " is updated to ";
    SET s1 = "";# 依次检测一条update操作是否对player的三个属性进行变更(id除外)
    IF
    	old.NAME <> new.NAME THEN	
    		SET s1 = CONCAT( s1, "name ", old.NAME, s2, new.NAME, "; " );
    END IF;
    IF
    	old.salary <> new.salary THEN		
    		SET s1 = CONCAT( s1, "salary ", old.salary, s2, new.salary, "; " );
    END IF;
    IF
    	old.team_id <> new.team_id THEN		
    		SET s1 = CONCAT( s1, "teams_id ", old.team_id, s2, new.team_id, "; " );
    	UPDATE teams 
    	SET nums = nums - 1 
    	WHERE
    		teams.id = old.team_id;
    	UPDATE teams 
    	SET nums = nums + 1 
    	WHERE
    		teams.id = new.team_id;
    END IF;
    INSERT INTO LOGS(log) VALUES(s1);
    END;
    ;;
    delimiter;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    drop trigger if exists update_player ;
    delimiter $$
    create trigger update_player
    after update
    on players
    for each row 
    begin
    	set @temp = '';
        if old.id != new.id then
    		set @temp = concat( @temp, "id ", old.id, " is update to ", new.id, '; ');
        end if;
    	if old.name != new.name then
    		set @temp = concat( @temp, " name ", old.name, " is update to ", new.name, '; ');
        end if;
        if old.salary != new.salary  then
    		set @temp = concat( @temp, " salary  ", old.salary , " is update to ", new.salary , '; ');
        end if;
    	if old.team_id != new.team_id  then
    		set @temp = concat( @temp, " team_id  ", old.team_id , " is update to ", new.team_id , '; ');
            update teams set teams.nums = teams.nums + 1 where teams.id = new.team_id;
    		update teams set teams.nums = teams.nums - 1 where teams.id = old.team_id;
        end if;
        
        if @temp != "" then
    		insert into logs(log) values(@temp);
        end if;
        
    end $$
    delimiter ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    基于SSH开发教师管理系统
    高等数学(第七版)同济大学 习题7-8 个人解答
    第五届美团网络安全高校挑战赛团体初赛writeup
    在任何机器人上实施 ROS 导航堆栈的指南
    C++的学习
    Oracle SQL基础
    [Machine Learning][Day1]监督学习和无监督学习
    MySQL8修改密码(linux环境)
    【SSL证书安全】
    KBEngine ue5
  • 原文地址:https://blog.csdn.net/JamSlade/article/details/128063951