MySQL多表&事务

MySQL多表&事务


    ### **多表查询**:
    
    ##### *内连接
    
    -- 隐式内连接
    select  表1.查询字段 , 表2.查询字段  from  表1 , 表2  where  表1.外键列  =  表2.主键;
    -- 显式内连接
    select  *  from 表1  [inner]  join 表2  on  条件;
    作用:查询两张有交集的数据.
    
    ##### *外连接
    
    -- 左连接
    SELECT 字段名  FROM 表1  LEFT [OUTER] JOIN 表2  ON 条件     (OUTER可以省略)
    作用:完全显示左表数据和与右边有交集的数据.
    
    -- 右连接
    SELECT 字段名  FROM 表1  RIGHT [OUTER ]JOIN 表2  ON 条件 
    作用:完全显示右表数据和与左边有交集的数据.
    
    ##### *子查询
    
    **单行单列:**  SELECT 查询字段  FROM 表 WHERE 字段=(子查询); 
    **多行单列 :** SELECT 查询字段  FROM 表 WHERE 字段  IN (子查询); 
    **多行多列 :**  SELECT 查询字段  FROM (子查询) 表别名 WHERE 条件; 
    注意:1.子查询结果只要是单列,则在WHERE 后面作为条件   
    ​         2.子查询结果只要是多列,则在FROM后面作为表进行二次查询
    
    ### 事务:
    
    概念:在执行多个SQL语句时,要么全部成功,要么全部失败.
    
    ##### 事务操作步骤:
    
    开启事务: start transaction; 
    回滚事务: rollback; 
    提交事务: commit; 
    
    ##### 事务的四大特征:
    
    **1.原子性:**是不可分割的最小操作单位,要么同时成功,要么同时失败
    **2.持久性:**当事务提交或者回滚后,数据库会持久化的保存数据.
    **3.隔离性:**多个事务之间,相互独立
    **4.一致性:**事务操作前后,数据总量不变
    
    ##### 事务的隔离级别引发的问题:
    
    **脏读 :**一个事务读取到了另一个事务中尚未提交的数据  
    **不可重复读 :**一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这是事务 update时引发的问题  
    **幻读 :**一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的,这是 insert 或 delete 时引发的问题
    
    #####  事务的隔离级别:
    
    **read uncommitted :读未提交**  
    产生的问题:脏读 ,不可重复读, 幻读
    **read committed :读已提交**(Oracle默认)
    产生的问题:不可重复读,幻读
    **repeatable read:可重复读**(MySQL默认)
    产生的问题:幻读
    **serializable:串行化**
    可以解决所有的问题
    注意:隔离级别越高,性能越差,安全性越高.
    数据库设置隔离级别:
    set global transaction isolation level 级别字符串; 
    数据库查询隔离级别:
    select @@tx_isolation;
    
    ### DCl数据库语句:
    
     DDL:  create / alter / drop  数据库操作
     DML:insert /update/delete 	数据操作
     DQL :select /show 		数据查询
     DCL :grant /revoke 		用户授权
    
    ##### 创建用户:
    
    **语法:CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';** 
    -- 创建user1 用户,只能在 localhost这个服务器登录mysql 服务器,密码为123 
    create user 'user1'@'localhost' identified by '123'; 
    -- 创建user2 用户可以在任何电脑上登录mysql 服务器,密码为123 
    create user 'user2'@'%' identified by '123';
    
    ##### 给用户授权:
    
    **语法:GRANT 权限 1, 权限 2... ON 数据库名.表名  TO '用户名'@'主机名';** 
    1.  给user1 用户分配对test这个数据库操作的权限:创建表,修改表,插入记录,更新记录,查询 
      grant  create,alter,insert,update,select  on test.*  to  'user1'@'localhost';  
    2.  给user2 用户分配所有权限,对所有数据库的所有表   
      grant all on *.* to 'user2'@'%'; 
    
    ##### 撤销授权:
    
    **语法:REVOKE   权限 1, 权限 2... ON 数据库.表名  from '用户名'@'主机名';** 
    -- 撤销user1 用户对test数据库所有表的操作的权限 
    revoke all on test.* from 'user1'@'localhost'; 
    
    ##### 查看权限:
    
    **语法:SHOW GRANTS FOR '用户名'@'主机名';** 
    
    ##### 删除用户:
    
    **语法:DROP USER '用户名'@'主机名';** 
    
    ##### 修改管理员密码:
    
    **语法:mysqladmin -uroot -p password 新密码**  -- 未登录数据库前操作
    
    ##### 修改普通用户密码:
    
    **语法:set password for '用户名'@'主机名' = password('新密码');  -- 登录数据库后操作**
    
    ##### =====================================================================================
    
    ### 案例语句:
    
    ```
    -- 创建部门表
    CREATE TABLE dept( 
       id INT PRIMARY KEY AUTO_INCREMENT, 
       NAME VARCHAR(20) 
    ) 
     -- 插入数据
    2INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部'); 
    
    -- 创建员工表
    CREATE TABLE emp ( 
       id INT PRIMARY KEY AUTO_INCREMENT, 
       NAME VARCHAR(10), 
       gender CHAR(1),    -- 性别 
       salary DOUBLE,    -- 工资 
       join_date DATE,   -- 入职日期 
       dept_id INT, 
       FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键) 
       )    
    
     -- 插入数据
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1); 
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2); 
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2); 
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3); 
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1); 
    ```
    
    ##### *多表查询
    
    ```
    SELECT * FROM emp  e ,dept d WHERE e.dept_id = d.id; 
    ```
    
    -- 查询员工和部门的名字 
    
    ```
    SELECT e.name, d.name FROM emp  e,dept  d WHERE e.dept_id = d.id; 
    ```
    
    ##### *隐式内连接查询
    
    -- 隐式内连接查询两张表数据
    
    ```
    SELECT * FROM emp,dept WHERE emp.dept_id = dept.id;
    ```
    
    ##### *显式内连接查询
    
    -- 显式内连接查询两张表数据
    
    ```
    SELECT e.id, e.name, d.name FROM emp e JOIN dept d ON e.dept_id=d.id;
    ```
    
    -- 查询唐僧的信息
    
    ```
    SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id WHERE emp.name='唐僧';
    ```
    
    -- 查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称
    
    ```
    SELECT e.id,e.name,e.gender,e.salary,d.name FROM emp e INNER JOIN dept d ON e.dept_id = d.id WHERE e.name='唐僧'; 
    ```
    
    -- 表名有点长,可以给表取别名,显示的字段名也使用别名 
    
    ```
    SELECT e.id 编号,e.name 姓名,e.gender 性别,e.salary 工资,d.name 部门名字 FROM emp e INNER JOIN dept d ON e.dept_id = d.id WHERE e.name='唐僧';
    ```
    
    ##### *左外连接查询
    
    -- 在部门表中增加一个销售部 
    
    ```
    INSERT INTO dept (NAME) VALUES ('销售部'); 
    SELECT * FROM dept; 
    ```
    
    -- 使用左外连接查询,左匹配右,有数据则显示,无数据则为null
    ``SELECT * FROM dept d LEFT JOIN emp e ON d.id = e.dept_id;``
    
    ##### *右外连接查询
    
    -- 在员工表中增加一个员工  
    `INSERT INTO emp VALUES (NULL, '沙僧','男',6666,'2013-12-05',NULL);` 
    
    -- 使用右外连接查询 ,右匹配左,有则显示,无则为空
    `SELECT * FROM dept RIGHT JOIN emp ON dept.id = emp.dept_id;`  
    
    ##### *使用子查询 
    
    `SELECT * FROM emp WHERE dept_id = (SELECT id FROM dept WHERE NAME='市场部');`
    
    -- 1) 查询最高工资是多少 
    `SELECT MAX(salary) FROM emp;` 
    
    -- 2) 根据最高工资到员工表查询到对应的员工信息 
    `SELECT * FROM emp WHERE salary = (SELECT MAX(salary) FROM emp);`
    
    -- 3) 到员工表查询小于平均的员工信息 
    `SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);` 
    
    -- 查询工资大于5000 的员工,来自于哪些部门的名字 
    `SELECT NAME FROM dept WHERE id IN (SELECT dept_id FROM emp WHERE salary > 5000);` 
    
    -- 查询开发部与财务部所有的员工信息 
    `select * from emp where dept_id in (select id from dept where name in('开发部','财务部'));` 
    
    -- 查询出2011 年以后入职的员工信息,包括部门名称 
    `SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date >='2011-1-1') e WHERE d.id= e.dept_id ;`
    
    ### 多表查询经典案例:
    
    ```
    -- 部门表
    CREATE TABLE dept (
      id INT PRIMARY KEY PRIMARY KEY, -- 部门id
      dname VARCHAR(50), -- 部门名称
      loc VARCHAR(50) -- 部门所在地
    );
    
    -- 添加4个部门
    INSERT INTO dept(id,dname,loc) VALUES 
    (10,'教研部','北京'),
    (20,'学工部','上海'),
    (30,'销售部','广州'),
    (40,'财务部','深圳');
    
    -- 职务表,职务名称,职务描述
    CREATE TABLE job (
      id INT PRIMARY KEY,
      jname VARCHAR(20),
      description VARCHAR(50)
    );
    
    -- 添加4个职务
    INSERT INTO job (id, jname, description) VALUES
    (1, '董事长', '管理整个公司,接单'),
    (2, '经理', '管理部门员工'),
    (3, '销售员', '向客人推销产品'),
    (4, '文员', '使用办公软件');
    
    -- 员工表
    CREATE TABLE emp (
      id INT PRIMARY KEY, -- 员工id
      ename VARCHAR(50), -- 员工姓名
      job_id INT, -- 职务id
      mgr INT , -- 上级领导
      joindate DATE, -- 入职日期
      salary DECIMAL(7,2), -- 工资
      bonus DECIMAL(7,2), -- 奖金
      dept_id INT, -- 所在部门编号
      CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
      CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
    );
    
    -- 添加员工
    INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
    (1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
    (1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
    (1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
    (1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
    (1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
    (1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
    (1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
    (1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
    (1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
    (1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
    (1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
    (1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
    (1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
    (1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);
    
    -- 工资等级表
    CREATE TABLE salarygrade (
      grade INT PRIMARY KEY,   -- 级别
      losalary INT,  -- 最低工资
      hisalary INT -- 最高工资
    );
    
    -- 添加5个工资等级
    INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
    (1,7000,12000),
    (2,12010,14000),
    (3,14010,20000),
    (4,20010,30000),
    (5,30010,99990);
    
    -- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
    SELECT
    	e.`id`, -- 员工编号
    	e.`ename`, -- 员工姓名
    	e.`salary`, -- 员工工资
    	j.`jname`, -- 职务名称
    	j.`description`  -- 职务描述
    FROM
    	emp e, job j
    WHERE
    	e.`job_id`=j.`id`;
    
    -- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
    SELECT
    	e.`id`, -- 员工编号
    	e.`ename`, -- 员工姓名
    	e.`salary`, -- 员工工资
    	j.`jname`, -- 职务名称
    	j.`description`,  -- 职务描述
    	d.`dname`, -- 部门名称
    	d.`loc`  -- 部门位置
    FROM
    	emp e, job j, dept d
    WHERE
    	e.`job_id`=j.`id` AND e.`dept_id`=d.`id`;   
       
    -- 3.查询员工姓名,工资,工资等级
    SELECT 
    	e.`ename`,
    	e.`salary`,
    	s.*
    FROM
    	emp e, salarygrade s
    WHERE
    	e.`salary` BETWEEN s.`losalary` AND s.`hisalary`;
    
    -- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
    SELECT 
    	e.`ename`, -- 员工姓名
    	e.`salary`, -- 工资
    	j.`jname`, -- 职务名称
    	j.`description`, -- 职务描述
    	d.`dname`, -- 部门名称
    	d.`loc`, -- 部门位置
    	s.`grade` -- 工资等级
    FROM
    	emp e, job j, dept d, salarygrade s
    
    WHERE
    	e.`job_id`=j.`id` AND 
    	e.`dept_id`=d.`id` AND 
    	e.`salary` BETWEEN s.`losalary` AND s.`hisalary`;
    
    -- 5.查询出部门编号、部门名称、部门位置、部门人数(此处用到表映射)
    SELECT 
    	d.`id`, -- 部门编号
    	d.`dname`, -- 部门名称
    	d.`loc`, -- 部门位置
    	t2.人数 -- 部门人数
    FROM
    	dept d, 
           (SELECT dept_id,COUNT(id) 人数 FROM emp GROUP BY dept_id) t2
    WHERE
    	d.`id`=t2.dept_id;
     
    -- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
    SELECT
    	e.`ename` 员工姓名,-- 员工姓名
    	e.`mgr`,	   -- 上级领导
    	e2.`id`,	   -- 领导id
    	e2.`ename` 上级领导 -- 领导
    FROM emp e
    LEFT JOIN emp e2
    ON e.`mgr`=e2.`id`;
    
    SELECT * FROM emp;
    ```
    
    ### 事务案例:
    
    ```
    -- 创建数据表 
    CREATE TABLE account ( 
      id INT PRIMARY KEY AUTO_INCREMENT, 
      NAME VARCHAR(10), 
      balance DOUBLE 
    ); 
    
    -- 添加数据 
    INSERT INTO account (NAME, balance) VALUES ('张三', 1000), ('李四', 1000); 
    -- 查询表
    SELECT *FROM account;
    -- 开启事务
    START TRANSACTION;
    -- 张三账号-500 
    UPDATE account SET balance = balance -500 WHERE NAME='张三'; 
    -- 一旦此处发生错误,数据就会回滚
    -- 李四账号+500 
    UPDATE account SET balance = balance +500 WHERE NAME='李四'; 
    -- 回滚事务
    ROLLBACK;
    -- 提交事务
    COMMIT;
    
    -- 查看MySQL是否开启自动提交事务,1表示开启,0表示关闭
    SELECT @@autocommit;
    
    -- 取消自动提交事务
    SET @@autocommit=0;
    ```
    
    ### 作业经典案例:
    
    ```
    CREATE TABLE emp (
      `empno` BIGINT(4) NOT NULL COMMENT '员工编号',
      `ename` VARCHAR(20) NOT NULL COMMENT '姓名',
      `job` VARCHAR(20) NOT NULL COMMENT '职位',
      `mgr` BIGINT(4) DEFAULT NULL COMMENT '上级领导编号',
      `hiredate` DATETIME DEFAULT NULL COMMENT '入职时间',
      `sal` DECIMAL(10,2) NOT NULL COMMENT '工资',
      `comm`  DECIMAL(10,2) DEFAULT NULL COMMENT '奖金',
      `deptno` VARCHAR(2) DEFAULT NULL COMMENT '部门编号'
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    
    -- alter table emp modify comm decimal(10,2)
    INSERT INTO emp VALUES
    (1001,'甘宁','文员',1013,'2000-12-07',8000.00,NULL,20),
    (1002,'黛绮丝','销售员',1006,'2001-02-20',16000.00,3000,30),
    (1003,'殷天正','销售员',1006,'2001-02-21',12500.00,5000,30),
    (1004,'刘备','经理',1009,'2001-04-02',29750.00,NULL,20),
    (1005,'谢逊','销售员',1006,'2001-09-28',12500.00,14000,30),
    (1006,'关羽','经理',1009,'2001-02-20',28500.00,NULL,30),
    (1007,'张飞','经理',1009,'2001-09-01',24500.00,NULL,10),
    (1008,'诸葛亮','分析师',1004,'2007-04-19',30000.00,NULL,20),
    (1009,'曾阿牛','董事长',NULL,'2001-11-17',50000.00,NULL,10),
    (1010,'韦一笑','销售员',1006,'2001-09-08',15000.00,0,30),
    (1011,'周泰','文员',1008,'2007-05-23',11000.00,NULL,20),
    (1012,'程普','文员',1006, '2001-12-03',9500.00,NULL,30),
    (1013,'庞统','分析师',1004, '2001-12-03',30000.00,NULL,20),
    (1014,'黄盖','文员',1007, '2002-01-23',13000.00,NULL,10),
    (1015,'张三','保洁员',1001,'2013-05-01',80000.00,50000,50);
    
    CREATE TABLE dept (
    `deptno` VARCHAR(2) DEFAULT NULL COMMENT '部门编号',
    `dname` VARCHAR(20) NOT NULL COMMENT '部门名称',
    `loc` VARCHAR(20) NOT NULL COMMENT '地址'
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    
    INSERT INTO dept VALUES('10','教研部','北京');
    INSERT INTO dept VALUES('20','学工部','上海');
    INSERT INTO dept VALUES('30','销售部','广州');
    INSERT INTO dept VALUES('40','财务部','武汉');
    
    CREATE TABLE salgrade(
    `grade` BIGINT(4) NOT NULL COMMENT '级别',
    `losal` DECIMAL(10,2) COMMENT'最低工资',
    `hisal` DECIMAL(10,2) COMMENT'最高工资'
    )
    INSERT INTO salgrade VALUES(1,7000,12000);
    INSERT INTO salgrade VALUES(2,12010,14000);
    INSERT INTO salgrade VALUES(3,14010,20000);
    INSERT INTO salgrade VALUES(4,20010,30000);
    INSERT INTO salgrade VALUES(5,30010,99990);
    
    CREATE TABLE sallevel(
    `job` VARCHAR(20) NOT NULL COMMENT '职位',
    `grade` BIGINT(4) NOT NULL COMMENT '级别'
    )DEFAULT CHARSET=utf8;
    
    
    INSERT INTO sallevel VALUES('文员',1 );
    INSERT INTO sallevel VALUES('销售员',2);
    INSERT INTO sallevel VALUES('经理',3);
    INSERT INTO sallevel VALUES('分析师',4);
    INSERT INTO sallevel VALUES('董事长',5);
    INSERT INTO sallevel VALUES('保洁员',5);
    
    CREATE TABLE profit (
    `year` BIGINT(4) COMMENT'年份',
    `zz`  BIGINT(4) COMMENT'利润率'
    )
    
    INSERT INTO profit VALUES(2010,100);
    INSERT INTO profit VALUES(2011,150);
    INSERT INTO profit VALUES(2012,250);
    INSERT INTO profit VALUES(2013,800);
    INSERT INTO profit VALUES(2014,1000);
    
    -- 1. 查出至少有一个员工的部门。显示部门编号deptno、部门名称dname、部门位置loc、部门人数。
    /*
    查询的表: emp,dept
    条件(关联关系)emp.deptno = dept.deptno
    查询的字段:部门编号deptno、部门名称dname、部门位置loc、部门人数。
    部门人数:需要根据部门进行分组group by ,聚合统计count(*)
    注意:在emp表中有个部门编号是存在的,但是没有部门名称,需要用到左外连接展示emp表中的所有数据
    */
    SELECT 
    	dept.deptno 部门编号,
    	dept.dname 部门名称,
    	dept.loc 部门位置,
    	COUNT(*) 部门人数
    FROM emp,dept 
    WHERE emp.deptno = dept.deptno 
    GROUP BY dept.deptno
    
    -- 修改后(左外连接)
    SELECT 
    	emp.deptno 部门编号,
    	dept.dname 部门名称,
    	dept.loc 部门位置,
    	COUNT(*) 部门人数
    FROM emp
    LEFT JOIN dept 
    ON emp.deptno = dept.deptno 
    GROUP BY dept.deptno
    
    -- 2. 列出所有员工的姓名及其直接上级的姓名
    /*
    查的表:emp,需要注意emp表中mgr就是上级的编号
    条件:自关联 emp e1(员工表)  emp e2(上级表)  e1.mgr = e2.empno
    查询的字段:员工的姓名e1.ename  上级的姓名e2.ename
    */
    SELECT 
    	e1.ename 员工的姓名,
    	e2.ename 上级的姓名
    FROM emp e1,emp e2 
    WHERE e1.mgr = e2.empno
    -- 修改后(左外连接)
    SELECT 
    	e1.ename 员工的姓名,
    	e2.ename 上级的姓名
    FROM emp e1
    LEFT JOIN emp e2 
    ON e1.mgr = e2.empno
    
    -- 3. 列出受雇日期早于直接上级的所有员工的编号、姓名、部门名称
    /*
    查的表:emp,需要注意emp表中mgr就是上级的编号 , 部门表dept
    条件:自关联 emp e1(员工表)  emp e2(上级表)  e1.mgr = e2.empno
    查询的字段:员工的姓名e1.ename  上级的姓名e2.ename 部门名称dept.dname
    */
    -- 单表
    SELECT 
    	e1.empno 员工的编号,
    	e1.ename 员工的姓名,
    	e1.deptno
    FROM emp e1
    LEFT JOIN emp e2 
    ON e1.mgr = e2.empno
    WHERE e1.hiredate < e2.hiredate
    
    -- 优化(将上面查询的结果作为一张表继续跟部门表关联)
    SELECT 
    	dept.dname 部门名称,
    	e.*
    FROM dept,
    (SELECT 
    	e1.empno 员工的编号,
    	e1.ename 员工的姓名,
    	e1.deptno
    FROM emp e1
    LEFT JOIN emp e2 
    ON e1.mgr = e2.empno
    WHERE e1.hiredate < e2.hiredate) e
    WHERE dept.deptno = e.deptno
    
    -- 4. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
    /*
    查询的表:dept ,emp
    条件: dept.deptno = emp .deptno 注意:需要查询部门表中的所有数据(把部门作为左表)
    字段: dept.dname emp.*
    */
    SELECT 
    	dept.dname 部门名称,
    	emp.* 	
    FROM dept 
    LEFT JOIN emp
    ON dept.deptno = emp .deptno
    
    -- 5. 列出最低薪金大于15000的各种工作及从事此工作的员工人数
    /*
    查表:emp
    条件:薪金大于15000 注意:需要根据工种统计有多少人(分组group by job  统计count(*))
    字段:工作emp.job
    */
    SELECT job 工作, COUNT(*) 人数 FROM emp WHERE sal > 15000 GROUP BY job ;
    SELECT job 工作, COUNT(*) 人数 FROM emp WHERE (sal+ IFNULL(comm,0)) > 15000 GROUP BY job ;
    SELECT job 工作, COUNT(*) 人数 FROM emp GROUP BY job HAVING MIN(sal) > 15000;
    SELECT job, COUNT(*) 总数 FROM emp GROUP BY job 
    HAVING job IN (SELECT s2.`job` FROM salgrade s1, sallevel s2 WHERE s1.`losal`>15000 AND s1.`grade`=s2.`grade`);
    
    -- 优化
    salgrade:工资等级表(最低工资和最高工资)
    sallevel:工种等级表(工种,等级)
    emp:统计人数
    -- 第一步:salgrade 和 sallevel 关联关系salgrade.grade = sallevel.grade 可以查出每个工种的最低工资
    SELECT * FROM salgrade, sallevel WHERE salgrade.grade = sallevel.grade 
    -- 第二步:查询最低工资大于15000的 salgrade.losal >15000
    SELECT * FROM salgrade, sallevel WHERE salgrade.grade = sallevel.grade AND salgrade.losal >15000
    -- 第三步:将上面查询到的数据作为一张表s,然后跟emp表关联(emp.job = s.job),再根据工种进行分组,统计有多少人
    -- 注意:表中有重复字段的时候一定要排除
    SELECT 
    	emp.job 工作,
    	COUNT(*) 人数
    FROM emp, 
    (SELECT sallevel.job FROM salgrade, sallevel WHERE salgrade.grade = sallevel.grade AND salgrade.losal >15000) s
    WHERE emp.job = s.job
    GROUP BY emp.job
    
    
    -- 6. 列出在销售部工作的员工的姓名, 假定不知道销售部的部门编号
    /*
    查表:emp,dept
    条件:emp.deptno = dept.deptno  dept.dname ='销售部'
    字段:员工的姓名emp.ename
    */
    SELECT 
    	emp.ename 员工姓名
    FROM emp,dept 
    WHERE emp.deptno = dept.deptno AND dept.dname ='销售部';
    
    -- 7. 列出薪金高于公司平均薪金的所有员工信息,所在部门名称,上级领导,工资等级
    -- 第一步:公司平均薪金
    SELECT AVG(sal) FROM emp
    -- 第二步:薪金高于平均薪金的员工信息
    SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp);
    -- 第三步:将上面查到的数据作为一张表s ,关联dept表(dept.deptno = s.deptno),注意需要所有员工(左表为s表)
    SELECT 
    	s.*,
    	dept.dname
    FROM 
    	(SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp)) s
    LEFT JOIN dept 
    ON s.deptno =dept.deptno 
    -- 第四步:求上级领导姓名,将第三步的结果作为一张表(员工表)t ,关联emp(上级表)(t.mgr = emp.empno)
    SELECT 
    	t.*,
    	emp.ename 上级领导
    FROM
    	(SELECT s.*,dept.dname 部门名称 FROM (SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp)) s
    	LEFT JOIN dept ON s.deptno =dept.deptno ) t
    LEFT JOIN emp 
    ON t.mgr = emp.empno
    -- 第五步:求工资等级,将第四步的结果作为一张表 r ,关联sallevel表(r.job = sallevel.job)
    SELECT 
    	r.*,
    	sallevel.grade 工资等级
    FROM 
    	(SELECT t.*,emp.ename 上级领导 FROM
    	(SELECT s.*,dept.dname 部门名称 FROM (SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp)) s
    	LEFT JOIN dept ON s.deptno =dept.deptno ) t
    LEFT JOIN emp 
    ON t.mgr = emp.empno) r, sallevel
    WHERE r.job = sallevel.job
    
    
    -- 8. 列出与庞统从事相同工作的所有员工及部门名称
    -- 第一步:查询庞统的工作 --结果是分析师
    SELECT job FROM emp WHERE emp.ename = '庞统'
    -- 第二步:查询emp中工作是分析师的所有员工
    SELECT * FROM emp WHERE emp.job =(SELECT job FROM emp WHERE emp.ename = '庞统')
    -- 第三步:将第二步的结果作为一张表 e 关联部门表dept 关联条件(e.deptno = dept.deptno)
    SELECT 
    	e.*,
    	dept.dname
    FROM
    (SELECT * FROM emp WHERE emp.job =(SELECT job FROM emp WHERE emp.ename = '庞统') )e, dept 
    WHERE e.deptno = dept.deptno
    
    
    -- 9. 列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称
    -- 第一步:求出在部门30工作的最高薪金   查询结果是28500
    SELECT MAX(sal) FROM emp WHERE emp.deptno = 30
    -- 第二步:查询emp表中薪金大于28500的所有员工
    SELECT emp.ename 员工姓名, emp.sal 薪金, emp.deptno FROM emp WHERE sal >(SELECT MAX(sal) FROM emp WHERE emp.deptno = 30)
    -- 第三步: 将第二步的结果作为一张表 e 关联部门表dept 关联条件(e.deptno = dept.deptno)
    SELECT 
    	e.*,
    	dept.dname 部门名称
    FROM  (SELECT emp.ename 员工姓名, emp.sal 薪金, emp.deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE emp.deptno = 30)) e
    LEFT JOIN dept
    ON e.deptno = dept.deptno
    
    
    -- 10. 查出年份、利润、年度增长比( 年度增长比 = (今年-去年)/去年 *100% )
    -- 内连接
    SELECT *,(p1.zz-p2.zz)/p2.zz  年度增长比 FROM profit p1, profit p2 WHERE p1.year = p2.year + 1
    -- 左外连接
    SELECT *,(p1.zz-p2.zz)/p2.zz  年度增长比 FROM profit p1 LEFT JOIN profit p2 ON p1.year = p2.year + 1
    
    
    -- 百分比效果的内连接
    SELECT *,CONCAT((p1.zz-p2.zz)/p2.zz*100,'%')  FROM profit p1, profit p2 WHERE p1.year = p2.year + 1
    -- 百分比效果的左外连接
    SELECT p1.year,CONCAT(
    			IFNULL(
    				ROUND((p1.zz-p2.zz)/p2.zz*100,2)
    			,0),
    		'%')  年度增长比
    FROM profit p1 LEFT JOIN profit p2 ON p1.year = p2.year + 1
    ```

### DCL语句案例:

-- 创建超级用户
CREATE USER 'user1'@'localhost' IDENTIFIED BY '123'; 
-- 创建普通用户
CREATE USER 'user2'@'%' IDENTIFIED BY '123'
-- 给用户1授权对day03数据库的权限
GRANT CREATE,ALTER,INSERT,UPDATE,SELECT ON day03.* TO 'user1'@'localhost';
-- 给用户2赋予超级权限
GRANT ALL ON *.* TO 'user2'@'%';
-- 撤销user1对day03数据库的表的权限
REVOKE ALL ON day03.* FROM 'user1'@'localhost';
-- 查看权限
SHOW GRANTS FOR 'user1'@'localhost';
-- 删除用户
DROP USER 'user2'@'%';
-- 删除管理员密码
mysqladmin -urood -p PASSWORD 123456  -- cmd界面,此处无分号结尾
-- 修改普通用户密码
SET PASSWORD FOR 'user1'@'localhost'=123456; -- SQLyong界面,此处有分号结尾 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值