MySQL索引及其MySQL函数

MySQL性能

分析

数据库查询效率低下

​ 我们进入公司进行项目开发往往关注的是业务需求和功能的实现,但是随着项目运行的时间增加,数据量也就增加了,这时会影响到我们数据库的查询性能。当数据达到千万级别,数据查询效率非常低。

硬件优化
​ 提升数据库服务器性能
软件优化
SQL优化、创建索引、数据库读写分离配置等

执行次数比较多的语句

  1. 增删改查操作,我们使用查询频次较高,8:2以上比例(查询对比增删改操作)
    适合使用创建索引的方式提升数据查询效率
  2. 增删改查操作,增删改操作频繁时,不适合使用创建索引方式提升查询效率。可以使用专业的搜索引擎技术完成搜索功能
    elasticsearch、solr …
-- 查询累计插入和返回数据条数  查询累计执行的CRUD操作
show global status like 'Innodb_rows%';

查看-sql语句的执行效率

  1. 插入千万条数据
create database day22;

use day22;

-- 1. 准备表
CREATE TABLE `user`(
	id INT,
	username VARCHAR(32),
	`password` VARCHAR(32),
	sex VARCHAR(6),
	email VARCHAR(50)
);

-- 2. 创建存储过程,实现批量插入记录
DELIMITER $$ -- 声明存储过程的结束符号为$$
CREATE PROCEDURE auto_insert()
BEGIN
    DECLARE i INT DEFAULT 1;
	START TRANSACTION; -- 开启事务
    WHILE(i<=10000000)DO
        INSERT INTO `user` VALUES(i,CONCAT('jack',i),MD5(i),'male',CONCAT('jack',i,'@itcast.cn'));
        SET i=i+1;
    END WHILE;
	COMMIT; -- 提交
END$$ -- 声明结束
DELIMITER ; -- 重新声明分号为结束符号

-- 3. 查看存储过程
SHOW CREATE PROCEDURE auto_insert;

-- 4. 调用存储过程
CALL auto_insert();
  1. 慢查询日志(没有快查询日志)
    查看SQL语句的执行情况(执行的相关参数)
-- 查看慢查询日志开启情况,mysql默认是关闭
show variables like '%slow_query_log%';
-- 开启慢查询日志
set global slow_query_log = on;
-- 查看慢查询时间配置
show variables like '%long_query_time%'; 
-- 查看慢查询日志更全参数:
show variables like '%query%';
-- 设置慢查询的sql时间阀值:
-- 全局配置(下次生效...)
set global long_query_time=3;
-- 临时(会话)配置(本次会话窗口生效)
set session long_query_time=3;

在这里插入图片描述
慢查询日志文件分析
在这里插入图片描述

MySQL索引

索引简介:

将数据进行排序整理的过程就称为索引
我们根据索引去查,提高查询效率
在这里插入图片描述

MySQL索引分类

  • 主键(约束)索引
    主键约束(非空且唯一) + 提升数据查询效率
  • 唯一(约束)索引 unique
    唯一约束 + 提升数据查询效率
  • 普通索引
    提升数据查询效率
  • 组合(联合)索引
    通过多列组成索引

MySQL索引语法

创建索引:

  1. 直接创建
    1. 创建普通索引
      create index 索引名 on 表名(列名);
    2. 创建唯一索引
      create unique index 索引名 on 表名(列名);
    3. 创建普通组合索引
      create index 索引名 on 表名(列名1,列名2 …);
    4. 创建唯一组合索引
      create unique index 索引名 on 表名(列名1,列名2 …);

-- 演示:
-- 创建学员表
CREATE TABLE stu(
	id INT,
	`name` VARCHAR(30),
	telephone VARCHAR(11)
);
-- 创建普通索引
CREATE INDEX name_idx ON stu(`name`);
-- 创建唯一索引
CREATE UNIQUE INDEX telephone_idx ON stu(telephone);
  1. 修改表时指定:(即在已有表上修改增添索引)
    1. 添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
      alter table 表名 add primary key(主键列);
    2. 添加唯一索引(除了NULL外,NULL可能会出现多次)
      alter table 表名 add unique(列名);
    3. 添加普通索引,索引值可以出现多次。
      alter table 表名 add index(列名);


-- 演示:
-- 修改表时,添加索引
-- 添加主键索引
ALTER TABLE stu ADD PRIMARY KEY(id);
-- 添加普通索引
ALTER TABLE stu ADD INDEX(`name`);
-- 添加唯一索引
ALTER TABLE stu ADD UNIQUE(telephone);
  1. 创建表时指定
-- 创建表时,直接指定索引
CREATE TABLE teacher(
	id INT PRIMARY KEY,  -- 主键索引
	`name` VARCHAR(30),
	sex VARCHAR(5),
	telephone VARCHAR(11) UNIQUE, -- 唯一索引
	INDEX(`name`) -- 普通索引
);

删除索引:

  1. 直接删除
    drop index 索引名 on 表名;

  2. 修改表时删除 【掌握】
    alter table 表名 drop index 索引名;

-- 删除索引
DROP INDEX name_idx ON stu;
-- 修改表时,删除索引
ALTER TABLE stu DROP INDEX telephone_idx;

千万条数据下索引效果演示:

  1. 没有索引情况下查询:
-- 基于id查询
select * from user where id=88;
-- 基于用户名等值查询
select * from user where username='jack1234567';
-- 基于邮箱模糊查询
select * from user where email like 'jack123467%';

在这里插入图片描述
可以看出时间花费了近6″,相对而言是很久的。

  1. 给这三个字段添加索引
-- 为id添加主键索引
alter table user add primary key(id);
-- 为用户名添加普通索引
alter table user add index(username);
-- 为邮箱添加唯一索引
alter table user add unique(email);
3. 测试有索引情况下查询
```sql
-- 基于id查询
select * from user where id=88;
-- 基于用户名等值查询
select * from user where username='jack1234567';
-- 基于邮箱模糊查询
select * from user where email like 'jack123467%';

在这里插入图片描述
可以看出,一瞬间即可查询出来我们所需数据

索引优缺点

  • 优点
    减少磁盘IO,大大提升查询效率

  • 缺点
    索引会占用磁盘空间
    我们在进行增删改操作时,需要重新维护索引,增加数据维护成本。消耗数据库服务器资源。例如:cpu、内存等

索引创建原则

  1. 字段内容可识别度不能低于70%
    字段内容不要存在大量相同的内容 例如:性别列

  2. 经常使用where条件搜索的字段 简单点说:经常作为查询条件的字段

  3. 经常使用表连接的字段(内连接、外连接)

  4. 经常排序的字段 order by 可以基于索引的数据结构排序,提升排序的效率

  • 注意:索引本身会占用磁盘空间,不是所有的字段都适合增加索引…

常见索引失效情况

-- 使用like模糊查询,通配符在最左侧时,索引失效  '%jack..'
select * from user where email like '%jack123467%';
-- 尽量避免在or查询条件中使用索引。条件中如果有任意一个条件没有索引,索引失效
select * from user where id=88 or sex='male';
-- 在索引列进行计算时,索引失效
select * from user where id+1=88-- 在使用 !=、 not in in、 is null is not null等,索引失效
select * from user where username is null;

索引的数据结构

2.8.1 概述

我们知道索引是帮助MySQL高效获取排好序数据结构
建立索引,通过数据结构对数据排序。减少磁盘io次数,提升数据查找效率
为什么使用索引后查询效率提高很多呢?接下来我们来了解下。

在这里插入图片描述
在没有索引的情况下我们执行一条sql语句,那么是表进行全局遍历,磁盘寻址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。

select  * from user where co1
为了加快的查找效率,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找快速获取到相应数据。
select  * from user where col2=89;

2.8.2 索引的数据结构

  1. 二叉树:左边子节点小于父节点,右边子节点大于父节点在这里插入图片描述
  2. 红黑树:平衡二叉树(左旋、右旋)
    在这里插入图片描述
  3. BTree:多路平衡二叉树在这里插入图片描述
  4. B+Tree:优化了BTree (mysql索引数据结构)在这里插入图片描述
  5. Hash:数据无序,不支持范围查询
    key-value数据结构
  6. MySQL中的B+Tree
-- 查看mysql索引节点大小
show global status like 'innodb_page_size';

在这里插入图片描述

推荐数据结构学习网站

推荐数据结构学习网站

数据库的存储引擎

MySQL存储引擎的不同,那么索引文件保存的方式也有所不同,常见的有二种存储引擎MyISAMInnoDB

MyISAM(非聚集索引)

MySQL5.5版本之前默认存储引擎

不支持事务、不支持外键约束

CREATE TABLE tab_myisam(
	id INT PRIMARY KEY AUTO_INCREMENT,
	age INT(3)
) ENGINE=MYISAM;

ALTER TABLE tab_myisam ADD INDEX(age);

INSERT INTO tab_myisam VALUES(1,20);
INSERT INTO tab_myisam VALUES(2,22);
INSERT INTO tab_myisam VALUES(3,22);

在这里插入图片描述
非聚集索引:在这里插入图片描述

InnoDB(聚集索引)

MySQL5.5版本之后默认存储引擎

支持事务管理、支持外键约束

CREATE TABLE tab_innodb(
	id INT PRIMARY KEY AUTO_INCREMENT,
	age INT
) ENGINE=INNODB;
ALTER TABLE tab_innodb ADD INDEX(age);

INSERT INTO tab_innodb VALUES(1,20);
INSERT INTO tab_innodb VALUES(2,22);
INSERT INTO tab_innodb VALUES(3,22);

在这里插入图片描述
在这里插入图片描述
聚集索引:在这里插入图片描述

MySQL函数

为了简化操作,mysql提供了大量的函数给程序员使用(比如你想输入当前时间,可以调用now()函数)

函数可以出现的位置:插入语句的values()中,更新语句中,删除语句中,查询语句及其子句中。

菜鸟教程

mysql提供了很多函数,通过SQL语句完成一些数据操作。
导入数据:后面练习用:

/*
SQLyog v10.2 
MySQL - 5.7.26 : Database - mysql_enhance
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`day21` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `day21`;

/*Table structure for table `dept` */

DROP TABLE IF EXISTS `dept`;

CREATE TABLE `dept` (
  `id` int(11) NOT NULL,
  `dname` varchar(50) DEFAULT NULL,
  `loc` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `dept` */

insert  into `dept`(`id`,`dname`,`loc`) values (10,'教研部','北京'),(20,'学工部','上海'),(30,'销售部','广州'),(40,'财务部','深圳');

/*Table structure for table `emp` */

DROP TABLE IF EXISTS `emp`;

CREATE TABLE `emp` (
  `id` int(11) NOT NULL,
  `ename` varchar(50) DEFAULT NULL,
  `job_id` int(11) DEFAULT NULL,
  `mgr` int(11) DEFAULT NULL,
  `joindate` date DEFAULT NULL,
  `salary` decimal(7,2) DEFAULT NULL,
  `bonus` decimal(7,2) DEFAULT NULL,
  `dept_id` int(11) DEFAULT NULL,
  `nickname` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `emp_jobid_ref_job_id_fk` (`job_id`),
  KEY `emp_deptid_ref_dept_id_fk` (`dept_id`),
  CONSTRAINT `emp_deptid_ref_dept_id_fk` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`id`),
  CONSTRAINT `emp_jobid_ref_job_id_fk` FOREIGN KEY (`job_id`) REFERENCES `job` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `emp` */

insert  into `emp`(`id`,`ename`,`job_id`,`mgr`,`joindate`,`salary`,`bonus`,`dept_id`,`nickname`) values (1001,'孙悟空',4,1004,'2010-12-17','8000.00',NULL,20,'sunwukong'),(1002,'卢俊义',3,1006,'2011-02-20','16000.00','3000.00',30,'lujunyi'),(1003,'林冲',3,1006,'2011-02-22','12500.00','5000.00',30,'linchong'),(1004,'唐僧',2,1009,'2011-04-02','29750.00',NULL,20,'tangseng'),(1005,'李逵',4,1006,'2011-09-28','12500.00','14000.00',30,'likui'),(1006,'宋江',2,1009,'2011-05-01','28500.00',NULL,30,'songjiang'),(1007,'刘备',2,1009,'2011-09-01','24500.00',NULL,10,'liubei'),(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20,'zhubajie'),(1009,'罗贯中',1,NULL,'2001-02-17','50000.00',NULL,10,'luoguanzhong'),(1010,'吴用',3,1006,'2008-09-08','15000.00','5000.00',30,'wuyong'),(1011,'沙僧',4,1004,'2009-05-23','11000.00','3000.00',20,'shaseng'),(1012,'李逵',4,1006,'2015-12-03','9500.00','5000.00',30,'likui'),(1013,'小白龙',4,1004,'2013-12-03','30000.00','3000.00',20,'xiaobailong'),(1014,'关羽',4,1007,'2002-02-23','13000.00',NULL,10,'guanyu');

/*Table structure for table `job` */

DROP TABLE IF EXISTS `job`;

CREATE TABLE `job` (
  `id` int(11) NOT NULL,
  `jname` varchar(20) DEFAULT NULL,
  `description` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `job` */

insert  into `job`(`id`,`jname`,`description`) values (1,'董事长','管理整个公司,接单'),(2,'经理','管理部门员工'),(3,'销售员','向客人推销产品'),(4,'文员','使用办公软件');

/*Table structure for table `salarygrade` */

DROP TABLE IF EXISTS `salarygrade`;

CREATE TABLE `salarygrade` (
  `grade` int(11) NOT NULL,
  `losalary` int(11) DEFAULT NULL,
  `hisalary` int(11) DEFAULT NULL,
  PRIMARY KEY (`grade`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*Data for the table `salarygrade` */

insert  into `salarygrade`(`grade`,`losalary`,`hisalary`) values (1,7000,12000),(2,12010,14000),(3,14010,20000),(4,20010,30000),(5,30010,99990);

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

字符串函数

常用:

  1. 函数:CONCAT(s1,s2…sn)
    描述:字符串 s1,s2 等多个字符串合并为一个字符串
    实例:SELECT CONCAT(‘传智播客’,’-’,‘黑马程序员’);

  2. 函数:CHAR_LENGTH(str)
    描述:返回字符串 str 的字符数
    实例:SELECT CHAR_LENGTH(‘传智播客’);

  3. 函数:LENGTH(str)
    描述:返回字符串 s 的字节数
    编码:UTF8(一个中文字符占3个字节)
    实例:SELECT LENGTH(‘itcast’);

  4. 函数:UCASE(s) | UPPER(s)
    描述:将字符串转换为大写
    实例:SELECT UCASE(‘itcast’);

  5. 函数:LCASE(s) | LOWER(s)
    描述:将字符串转换为小写
    实例:SELECT LCASE(‘ITCAST’);

  6. 函数:LOCATE(s1,s)
    描述:从字符串 s 中获取 s1 的开始位置
    注意:从1开始
    实例:SELECT LOCATE(‘ca’,‘itcast’);

  7. 函数:TRIM(str) | LTRIM(str) | RTRIM(str)
    描述:字符串去空格
    实例:SELECT TRIM(’ itcast ');

  8. 函数:REPLACE(s,s1,s2)
    描述:将字符串 s2 替代字符串 s 中的字符串 s1
    实例:SELECT REPLACE(‘itcast’,‘ca’,‘bbc’);

  9. 函数:SUBSTR(s, start, length)
    描述:从字符串 s 的 start 位置截取长度为 length 的子字符串
    注意:从1开始
    实例:SELECT SUBSTR(‘itcast’,3,10);

  10. 函数:STRCMP(str1,str2)
    描述:比较字符串大小,左大于右时返回1,左等于右时返回0,,左小于于右时返回-1,
    实例:SELECT STRCMP(‘acc’,‘abc’);

代码演示:
-- 将所有员工的昵称改为大写
SELECT UCASE(nickname) FROM emp;

-- 显示所有员工的姓氏,截取
SELECT ename,SUBSTR(ename,1,1) FROM emp;

-- 显示所有员工姓名字符长度
SELECT ename,CHAR_LENGTH(ename) FROM emp; 

-- 显示所有员工姓名字节长度
SELECT ename,LENGTH(ename) FROM emp; 

-- 将所有姓李的员工,姓氏替换为li
SELECT ename,REPLACE(ename,'李','li') FROM emp;
-- mysql函数可以嵌套使用
SELECT ename,REPLACE(SUBSTR(ename,1,1),'李','li') FROM emp;

-- 将所有员工的姓名和昵称拼接在一起
SELECT CONCAT(ename,nickname) FROM emp;

日期函数

常用:

  1. 函数:NOW() | CURDATE() | CURTIME()
    描述:获取系统当前日期时间、日期、时间
    实例:SELECT NOW();

  2. 函数:YEAR(DATE) | MONTH(DATE) | DAY(DATE)
    描述:从日期中选择出年、月、日
    实例:SELECT YEAR(NOW());

  3. 函数:LAST_DAY(DATE)
    描述:返回月份的最后一天
    实例:SELECT LAST_DAY(‘2019-2-1’);

  4. 函数:ADDDATE(DATE,n) | SUBDATE(DATE,n)
    描述:计算起始日期 DATE 加(减) n 天的日期
    实例:SELECT SUBDATE(NOW(),7);

  5. 函数:QUARTER(DATE)
    描述:返回日期 DATE 是第几季节,返回 1 到 4
    实例:SELECT QUARTER(‘2020-05-03’);

  6. 函数:DATEDIFF(d1,d2)
    描述:计算日期 d1->d2 之间相隔的天数
    实例:SELECT DATEDIFF(NOW(),‘1999-9-9’);

  7. 函数:DATE_FORMAT(d,f)
    描述:按表达式 f的要求显示日期 d
    实例:SELECT DATE_FORMAT(NOW(),’%Y-%m-%d’);

代码演示:
-- 统计每个员工入职的天数
SELECT ename,DATEDIFF(NOW(),joindate) FROM emp;

-- 统计每个员工的工龄 (以一年365天为例)
SELECT ename,DATEDIFF(NOW(),joindate)/365 FROM emp;

-- 查询2011年入职的员工
SELECT * FROM emp WHERE YEAR(joindate)='2011';

-- 统计入职10年以上的员工信息
SELECT * FROM emp WHERE DATEDIFF(NOW(),joindate)/365>10;

数字函数

常用

  1. 函数:ABS(x)
    描述:返回 x 的绝对值
    实例:SELECT ABS(-10);

  2. 函数:CEIL(x) | FLOOR(x)
    描述:向上(下)取整
    实例:SELECT FLOOR(3.6);

  3. 函数:MOD(x,y)
    描述:返回x mod y的结果,取余
    实例:SELECT MOD(5,4);

  4. 函数:RAND()
    描述:返回 0 到 1 的随机数
    实例:SELECT RAND();

  5. 函数:ROUND(x)
    描述:四舍五入
    实例:SELECT ROUND(10.665);

  6. 函数:TRUNCATE(x,y)
    描述:返回数值 x 保留到小数点后 y 位的值
    实例:SELECT TRUNCATE(10.665,2);

代码演示:

-- 统计每个员工的工龄,超过半年的算一年
SELECT ename,ROUND(DATEDIFF(NOW(),joindate)/365) FROM emp;

--  统计每个部门的平均薪资,保留2位小数  (avg + 分组)
SELECT e.dept_id,d.dname,TRUNCATE(AVG(e.salary),2) FROM emp e 
 INNER JOIN dept d ON e.`dept_id`=d.id GROUP BY e.dept_id;

--  统计每个部门的平均薪资,小数向上取整
SELECT e.dept_id,d.dname,CEIL(AVG(e.salary)) FROM emp e 
 INNER JOIN dept d ON e.`dept_id`=d.id GROUP BY e.dept_id;
 
 
-- 统计每个部门的平均薪资,小数向下取整
SELECT e.dept_id,d.dname,FLOOR(AVG(e.salary)) FROM emp e 
 INNER JOIN dept d ON e.`dept_id`=d.id GROUP BY e.dept_id;

高级函数

CASE表达式

相当于java中swtich语句
语法:

select
	case 列名
		when 值1 then 希望得到的值1
		when 值2 then 希望得到的值2
		...
		else 前面的条件都无法满足的情况获取到的值
	end
from 表名
代码演示
-- 查询每个员工的工资等级并排序
-- 工资等级在1显示为 '努力赚钱'
-- 工资等级在2显示为 '小康生活'
-- 工资等级在3显示为 '可以娶媳妇'
-- 工资等级在4显示为 '可以买车'
-- 工资等级在5显示为 '可以买房'
-- 工资等级不在以上列表中显示为 '土豪'

-- 1.1 确定几张表
SELECT * FROM emp e INNER JOIN salarygrade sg;
-- 1.2 确定关联关系
SELECT * FROM emp e INNER JOIN salarygrade sg 
	ON e.`salary` BETWEEN sg.`losalary` AND sg.`hisalary`;
-- 1.3 确定显示的列
SELECT e.`ename`,e.`salary`,sg.`grade` FROM emp e INNER JOIN salarygrade sg 
     ON e.`salary` BETWEEN sg.`losalary` AND sg.`hisalary` ORDER BY sg.`grade` ASC;
-- 1.4 确定业务条件,展示生活状态
SELECT e.`ename`,e.`salary`,sg.`grade`,
	CASE sg.`grade`
		WHEN 1 THEN '努力赚钱'
		WHEN 2 THEN '小康生活'
		WHEN 3 THEN '可以娶媳妇'
		WHEN 4 THEN '可以买车'
		WHEN 5 THEN '可以买房'
		ELSE '土豪'
	END AS '生活状态'
 FROM emp e INNER JOIN salarygrade sg 
     ON e.`salary` BETWEEN sg.`losalary` AND sg.`hisalary` ORDER BY sg.`grade` ASC;

IF表达式

相当于java中三元运算符 表达式?值1:值2
语法:
select if(1>0,‘真’,‘假’) from 表名

代码演示:

-- 工资+奖金大于20000的员工 显示家有娇妻,否则显示单身狗
SELECT ename,IF(salary+IFNULL(bonus,0)>20000,'家有娇妻','单身狗') AS '感情状态' FROM emp;

MySQL综合练习

-- 1.计算员工的日薪(按30天),保留二位小数
SELECT ename,TRUNCATE(salary/30,2) AS '日薪' FROM emp;

-- 2.计算出员工的年薪(12月),并且以年薪排序 降序
SELECT ename,salary*12 AS totalSalary FROM emp ORDER BY totalSalary DESC;

-- 3.找出奖金少于5000或者没有获得奖金的员工的信息
SELECT * FROM emp WHERE bonus<5000 OR bonus IS NULL;
SELECT * FROM emp WHERE IFNULL(bonus,0)<5000;

-- 4.返回员工职务名称及其从事此职务的最低工资  (分组+聚合(min))
-- 4.1 确定几张表
SELECT * FROM emp e INNER JOIN job j;
-- 4.2 确定关联关联,消除笛卡尔积
SELECT * FROM emp e INNER JOIN job j ON e.`job_id`=j.`id`;
-- 4.3 确定显示的字段
SELECT j.`jname`,MIN(e.salary) FROM emp e
 INNER JOIN job j ON e.`job_id`=j.`id` GROUP BY e.job_id;

-- 5.返回工龄超过10年,且2月份入职的员工信息
SELECT * FROM emp WHERE DATEDIFF(NOW(),joindate)/365>10 AND MONTH(joindate)='02';

-- 6.返回与 林冲 同一年入职的员工
-- 查询林冲入职的年份
SELECT YEAR(joindate) FROM emp WHERE ename='林冲';
SELECT * FROM emp WHERE YEAR(joindate)=
	(SELECT YEAR(joindate) FROM emp WHERE ename='林冲');

-- 7.返回每个员工的名称及其上级领导的名称(自关联)
SELECT yuangong.ename,lingdao.ename FROM emp yuangong
	LEFT JOIN emp lingdao ON yuangong.mgr=lingdao.id;

-- 8.返回工资为二等级(工资等级表)的职员名字(员工表)、部门名称(部门表)
-- 8.1 确定几张表
SELECT * FROM  emp e,dept d,salarygrade sg;
-- 8.2 确定关联关系
SELECT * FROM emp e INNER JOIN dept d ON e.dept_id=d.id
	INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 8.3 确定显示的列
SELECT e.ename,d.dname FROM emp e INNER JOIN dept d ON e.dept_id=d.id
	INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary;
-- 8.4 确定业务条件
SELECT e.ename,d.dname FROM emp e INNER JOIN dept d ON e.dept_id=d.id
	INNER JOIN salarygrade sg ON e.salary BETWEEN sg.losalary AND sg.hisalary
	WHERE sg.grade=2;

-- 9.涨工资:董事长2000 经理1500 其他800
-- 9.1 确定几张表
SELECT * FROM emp e,job j;
-- 9.2 确定关联关系
SELECT * FROM emp e INNER JOIN job j ON e.job_id=j.id;
-- 9.3 确定要显示的列
SELECT e.ename,j.jname,e.salary '涨薪前',
	CASE j.jname
		WHEN '董事长' THEN e.salary+2000
		WHEN '经理' THEN e.salary+1500
		ELSE e.salary+800
	END AS '涨薪后'
FROM emp e INNER JOIN job j ON e.job_id=j.id;

版权声明:本文为weixin_45144691原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。