SQL作业

-- 查询月薪最高的员工姓名和工资 - 子查询/嵌套查询+聚合函数
-- select ename, sal from tb_emp order by sal desc limit 1;
select ename, sal from tb_emp where sal=(
select max(sal) from tb_emp
);

-- 查询员工的姓名和年薪((月薪+补贴)12)
select ename, (sal+ifnull(comm, 0))12 as 年薪 from tb_emp order by 年薪 desc;

-- 查询有员工的部门的编号和人数 - 分组查询+聚合函数
select dno, count(dno) from tb_emp group by dno with rollup;

-- 查询所有部门的名称和人数 - 子查询+连接查询(左外)
select dname as 部门名称, ifnull(total, 0) as 人数 from tb_dept t1 left join (select dno, count(dno) as total from tb_emp group by dno) t2 on t1.dno=t2.dno;

-- 查询月薪最高的员工(Boss除外)的姓名和工资 - 空值判断
select ename, sal from tb_emp where sal=(select max(sal) from tb_emp where mgr is not null);

-- 查询月薪超过平均薪水的员工的姓名和工资
select ename, sal from tb_emp where sal>(select avg(sal) as avgsal from tb_emp);

-- 查询月薪超过其所在部门平均薪水的员工的姓名、部门编号和工资
select ename, t1.dno, sal, round(agvsal, 2) from tb_emp t1 inner join (select dno, avg(sal) as avgsal from tb_emp group by dno) t2 on t1.dno=t2.dno where sal>avgsal;

-- 查询部门中薪水最高的人姓名、工资和所在部门名称
select ename, sal, dname from (select ename, sal, t1.dno from tb_emp t1 inner join (select dno, max(sal) as maxsal from tb_emp group by dno) t2 on t1.dno=t2.dno where sal=maxsal) t3 inner join tb_dept t4 on t3.dno=t4.dno;

-- 查询主管的姓名和职位
select ename, job from tb_emp where eno in (select distinct mgr from tb_emp where mgr is not null);

-- 通常不推荐使用in或者not in集合运算和distinct去重操作
-- 可以考虑用exists或not exists替代掉集合运算和去重操作
select ename, job from tb_emp t1 where exists (select 'x' from tb_emp t2 where t1.eno=t2.mgr);

select 'x';
select 'x' from dual;
select 'x' from tb_emp;
select 'x' from tb_emp where eno=7800;
select 'x' from tb_emp where eno=7900;
select 'x' from dual where exists (select * from tb_emp where ename like '张%');
select 'x' from dual where not exists (select * from tb_emp where ename like '王%');

-- 查询月薪排名4~6名的员工姓名和工资
select ename, sal from tb_emp order by sal desc limit 3, 3;
select ename, sal from tb_emp order by sal desc limit 3 offset 3;

-- (存储)过程/函数:把一系列的SQL可以封装到一个过程中,而且可以加上分支和循环,将来通过过程的名字直接调用过程即可,因为创建过程时已经提前编译了SQL语句,所以比直接执行SQL语句性能更好

delimiter $$

create procedure sp_dept_avg_sal(deptno int, out avgsal float)
begin
select avg(sal) into avgsal from tb_emp where dno=deptno;
end$$

delimiter ;

call sp_dept_avg_sal(20, @a);

-- 索引(index)
-- 索引可以加速查询所以应该在经常用于查询筛选条件的列上建立索引
-- 索引会使用额外的存储空间而且会让增删改变得更慢(因为要更新索引)
-- 所以不能够滥用索引
create index idx_emp_ename on tb_emp (ename);
drop index idx_emp_ename on tb_emp;

-- 视图:查询的快照(简化查询操作)
-- 通过视图可以将用户的访问权限限制到某些指定的列上
create view vw_emp_dept as
select eno, ename, dname from tb_emp t1 inner join tb_dept t2 on t1.dno=t2.dno;

select ename, dname from vw_emp_dept;

drop view vw_emp_dept;

-- explain生成执行计划
explain select eno, ename from tb_emp where eno=7800;
explain select eno, ename from tb_emp where eno<>7900;
explain select eno, ename from tb_emp where ename='张三丰';
explain select eno, ename from tb_emp where ename like '张%';
explain select eno, ename from tb_emp where ename like '%张';
explain select eno, ename from tb_emp where ename<>'张三丰';

-- 触发器:在执行增删改操作时可以触发其他的级联操作,但是有可能导致“锁表”现象,因此实际开发中应该避免使用触发器。

-- update tb_dept set dno=11 where dno=10;
-- delete from tb_dept where dno=11;

delimiter $$

create trigger tr_dept_update
after update on tb_dept for each row
begin
update tb_emp set dno=new.dno where dno=old.dno;
end$$

delimiter ;

drop trigger tr_dept_update;

-- DCL:授予权限(grant to)和召回权限(revoke from)
create user 'hellokitty'@'%' identified by '123123';

grant all privileges on hrs.* to 'hellokitty'@'%';

revoke insert, delete, update on hrs.* from 'hellokitty'@'%';

drop user 'hellokitty'@'%';

-- 事务(transaction)- 把多个增删改的操作做成不可分割的原子性操作
-- 要么全部都做,要么全都不做

-- start transaction;
-- 开启事务环境
begin;

delete from tb_emp;

-- 提交(事务中的所有操作全都生效)
commit;
-- 回滚(事务中的所有操作全部撤销)
rollback;

你可能感兴趣的:(SQL作业)