您的位置:首页 > 数据库 > MySQL

MySQLl快速入门笔记加基本查询练习

2020-02-06 18:01 696 查看

###MySQL学习笔记

####一,学习目标

1.进行复杂度较高的数据交换业务处理

2.灵活的操作数据库中的数据

3.掌握数据库设计技能

####二,初识MySQL

#####2.1 本章任务

1.使用SQL语句创建数据库myschool

2.使用SQL语句创建学生表student

3.使用SQL语句创建科目表subject

4.使用SQL语句创建成绩表result

5.使用SQL语句创建/删除年级表grade数据库中包含表、关系以及操作对象

#####2.2 本章目标

1.了解数据库的相关知识

2.掌握MySQL在Windows系统中的安装方法**(重点)**

3.学会使用SQLyog数据库管理工具

4.掌握MySQL命令行操作数据库常用命令 (重点)

5.了解SQL的相关概念

6.掌握创建库的SQL语句 (重点)

7.掌握创建数据表以及数据字段的类型和属性 (重点)

8.掌握修改表的SQL语句 (重点)

9.掌握使用SQL语句修改、删除表

10.掌握添加/删除约束的SQL语句 (重点)

11.掌握简单子查询的用法 (重点)

12.掌握IN子查询的用法 (重点)

#####2.3 为何需要数据库?

2.3.1 我们日常生活中存储数据的方法:
第一种方法:用大脑来记住数据  /*(此种方式容易遗忘)*/

第二种方法:写在纸上   /*(容易丢失,不便管理,可读性较差)*/

第三种方法:写在计算机的内存中   /*(容易丢失)*/

第四种方法:写成磁盘文件……   /*(保存传输方便,但数据格式不好统一)*/

######2.3.2 数据库能够做什么

1.存储大量数据,方便检索和访问

2.保持数据信息的一致、完整

3.共享和安全

4.通过组合分析,产生新的有用信息
2.4 时下流行的数据库

​ Oracle公司的产品,产品免费、服务收费

​ 针对不同用户群体的多个版本易用性好

​ 开放源代码网站应用广泛

2.5 数据库的基本概念
#数据库就是“数据”的“仓库”
#数据库中包含表、关系以及操作对象
#数据存放在表中
2.6 MySQL数据库的优势
#运行速度快
#使用成本低
#可移植性强
#适用用户广

MySQL社区版:免费,开源,适合普通用户

MySQL企业版:收费,不可自由下载,功能和服务更完善,适合对功能和安全要求高的企业用户

2.7 结构化查询语言

SQL(Structured Query Language):结构化查询语言

2.7.1 数据定义语言(DDL):
#用来创建或者删除数据库对象
比如:
1)create 创建数据库对象
2)drop 删除数据库对象
3)alert 修改数据库对象
2.7.2 数据操作语言(DML):
#用来操作数据库中包含的数据
比如:
1)insert  插入数据操作
2)update  修改数据操作
3)delete  删除数据操作
2.7.3 数据查询语言(DQL):
#用来对数据库中的数据进行查询
比如:Select   查询数据
2.7.4 数据控制语言(DCL):
#用来控制数据库的存取许可,存取权限等
比如:
1)grant
2) commit 提交
3)rollback 回滚
2.8 DDL(数据定义)语句
2.8.1 创建和删除数据库

1.创建数据库

# 格式: create database 数据库名
# 比如创建名为wzry的数据库
create database wzry;   # 注意:因为创建数据库时一次只创建一个,所以用的是单数 database

# 创建数据库时同时设置数据库的编码
# 格式:create database 数据库名 charset=编码
# 比如创建名为wzry的数据库,并将编码设置为utf8
create database wzry charset=utf8;

# 创建完数据库后可以查看数据库:
# 格式: show databases; 注意:查看数据库时,可能查看到的是多个数据库名称,所以此处用的是复数databases

2.删除数据库

# 格式:drop database 数据库名
# 比如:删除名为wzry的数据库
drop database wzry;

# 删除之后,可以用show databases ; 查看一下是否删除成功
2.8.2 创建数据库表格
# 格式:
CREATE TABLE [IF NOT EXISTS]  表名 (
字段1 数据类型 [字段属性|约束][索引][注释],
……
字段n 数据类型 [字段属性|约束][索引][注释]
)[表类型][表字符集][注释];

# 比如:创建student表
CREATE TABLE student(
studentNo INT(4)  PRIMARY KEY,
name CHAR(10),
…
);

# 注意:
# 1.mysql中关键字不区分大小写,create 和CREATE 效果一样
# 2.多字段使用逗号分隔
# 3.最后一个字段类型后面不加逗号
# 4.IF NOT EXISTS 表示如果不存在,create table if not exists 表名 表示如果数据库中不存在表名对应的表就创建,如果存在就不创建。
# 5.int 表示整数类型 int(4) 表示该字段的长度最大为4
# 6.char 表示定长字符串 char(10)表示字符串的长度为10

# 案例:在wzry数据库中创建一个hero表
create table hero(
id int,
name varchar(20),
level int,
loc varchar(20)
);
2.8.3 mysql数据类型
类型 说明 取值范围 存储需求
TINYINT 非常小的数据 有符值: -27 ~ 27-1 无符号值:0 ~ 28-1 1字节
SMALLINT 较小的数据 有符值: -215 ~ 215-1 无符号值: 0 ~ 216-1 2字节
MEDIUMINT 中等大小的数据 有符值: -223 ~ 223-1 无符号值: 0 ~ 224-1 3字节
INT 标准整数 有符值: -231 ~ 231-1 无符号值:0 ~ 232-1 4字节
BIGINT 较大的整数 有符值: -263 ~263-1无符号值:0 ~264-1 8字节
FLOAT 单精度浮点数 ±1.1754351e -38 4字节
DOUBLE 双精度浮点数 ±2.2250738585072014e -308 8字节
DECIMAL 字符串形式的浮点数 Decimal(M,D) M+2个字节
字符串类型 说明 长度
CHAR[(M)] 定长字符串 M字节
VARCHAR[(M)] 可变字符串 可变长度
TINYTEXT 微型文本串 0~28–1字节
TEXT 文本串 0~216–1字节
日期类型 格式 取值范围
DATE YYYY-MM-DD,日期格式 1000-01-01~ 9999-12-31
DATETIME YY-MM-DD hh:mm:ss: 1000-01-01 00:00:00 ~9999-12-31 23:59:59
TIME hh:mm:ss: -835:59:59 ~ 838:59:59
TIMESTAMP YYYYMMDDHHMMSS 1970年某时刻~2038年某时刻,精度为1秒
YEAR YYYY格式的年份 1901~2155

若某日期字段默认值为当前日期,一般设置为TIMESTAMP类型

2.8.4字段约束
名称 关键字 说明
非空约束 NOT NULL 字段不允许为空
默认约束 DEFAULT 赋予某字段默认值
唯一约束 UNIQUE KEY(UK) 设置字段的值是唯一的 允许为空,但只能有一个空值
主键约束 PRIMARY KEY(PK) 设置该字段为表的主键可唯一标识该表记录
外键约束 FOREIGN KEY(FK) 用于在两表之间建立关系, 需要指定引用主表的哪一字段
自动增长 AUTO_INCREMENT 设置该列为自增字段 默认每条自增1 通常用于设置主键

1.主键约束

CREATE TABLE student( studentNo INT(4) PRIMARY KEY, ……);

2.注释

​ CREATE TABLE test (

​ id int(11) COMMENT ‘编号’

​ )COMMENT='测试表’ ;

3.设置字符编码集

CREATE TABLE [IF NOT EXISTS] 表名(

​ 省略代码

CHARSET = 字符集名;

2.8.5 综合案例创建Student表
CREATE TABLE student(
studentNo INT(4) NOT NULL COMMENT '学号' PRIMARY KEY,
loginPwd VARCHAR(20) NOT NULL COMMENT '密码',
studentName VARCHAR(50) NOT NULL COMMENT '学生姓名',
sex CHAR(2) DEFAULT '男' NOT NULL  COMMENT '性别',
gradeId INT(4)  UNSIGNED COMMENT '年级编号',
phone VARCHAR(50)  COMMENT '联系电话',
address VARCHAR(255)  DEFAULT '地址不详'COMMENT '地址',
bornDate DATETIME  COMMENT '出生时间',
email VARCHAR(50) COMMENT'邮件账号',
identityCard VARCHAR(18)  UNIQUE KEY COMMENT '身份证号'
) COMMENT='学生表';
2.8.6 查看表结构
# 格式: desc 表名;
# 查看student表结构
desc student;
2.8.7 删除表
# 格式:DROP TABLE [IF  EXISTS] 表名;
#注意:IF EXISTS 表示判断表是否存在,可以省略,
#     不过一般建议在删除表之前,先使用IF EXISTS语句验证表是否存在
# 比如删除student表
drop table if exists student;
2.8.8 修改表
#修改表名
ALTER TABLE 旧表名 RENAME [TO]  新表名;

#添加字段
ALTER TABLE 表名 ADD 字段名  数据类型  [属性];

#修改字段
ALTER TABLE 表名 CHANGE 原字段名 新字段名 数据类型 [属性];

#删除字段
ALTER TABLE 表名 DROP 字段名;

#添加主键
ALTER TABLE 表名 ADD CONSTRAINT 主键名 PRIMARY KEY 表名(主键字段);

#添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名  FOREIGN KEY (外键字段) REFERENCES 关联表名(关联字段);

案例:

DROP TABLE IF EXISTS demo01;
#创建表
CREATE TABLE  demo01(
id INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(8) NOT NULL
);
#修改表名
ALTER TABLE demo01 RENAME demo02;
#添加字段
ALTER TABLE demo02 ADD `password` VARCHAR(32) NOT NULL;
#修改字段
ALTER TABLE  demo02  CHANGE `name` `username`CHAR(10) NOT NULL;
#删除字段
ALTER TABLE demo02 DROP `password`;

# 如何设置grade表中gradeId字段为主键?
# 参考代码
ALTER TABLE grade ADD CONSTRAINT pk_grade   PRIMARY KEY grade(gradeId);

# 如何将student表的gradeId字段和grade表的gradeId字段建立外键关联?
# 参考代码
ALTER TABLE `student`  ADD  CONSTRAINT fk_student_grade FOREIGN KEY(`gradeId`)
REFERENCES `grade` (`gradeId`);
2.9 MySQL的存储引擎

存储引擎的类型:MyISAMInnoDB 、Memory、CSV等

MyISAM与InnoDB类型主要区别

名称 InnoDB MyISAM
事务处理 支持 不支持
数据行锁定 支持 不支持
外键约束 支持 不支持
全文索引 不支持 支持
表空间大小 较大,约2倍 较小

适用场合

使用MyISAM: 不需事务,空间小,以查询访问为主

使用InnoDB: 多删除、更新操作,安全性高,事务处理及并发控制

查看当前默认存储引擎

SHOW VARIABLES LIKE ‘storage_engine%’;

修改默认的存储引擎

打开my.ini配置文件修改:

default-storage-engine= InnoDB (可以将InnoDB修改为其他引擎

设置表的存储引擎

CREATE TABLE 表名(
#省略代码
)ENGINE=存储引擎;

# 案例
CREATE TABLE mydemo (
id  INT(4)
)ENGINE=MyISAM;
2.10 DML(数据管理)语句

######2.101 插入数据

1.插入单条数据

# 格式:
# INSERT INTO 表名 [(字段名列表)] VALUES (值列表);
#注意:
#1.字段名是可选的,如省略则依次插入所有字段
#2.多个列表和多个值之间使用逗号分隔
#3.值列表和字段名列表一一对应
#4.如插入的是表中部分数据,字段名列表必填

# 案例:
INSERT INTO student(loginPwd,studentName,gradeId,phone,bornDate)
VALUES('123','黄小平',1,'13956799999','1996-5-8');

2.插入多条数据

#格式:INSERT INTO 新表(字段名列表)VALUES(值列表1),(值列表2),……,(值列表n);
#案例:
INSERT INTO subject(subjectName,classHour,gradeID)
VALUES('Logic Java',220,1),('HTML',160,1),('Java OOP',230,2);

#注意:为避免表结构发生变化引发的错误,建议插入数据时写明具体字段名!

3.将查询的结果加入到插入新表

# 格式:CREATE TABLE 新表(SELECT 字段1,字段2……  FROM 原表);
# 问题:编写SQL语句实现从学生表提取姓名、手机号两列数据存储到通讯录表中
# 参考代码:
CREATE TABLE phoneList(
SELECT studentName,phone
FROM student);
# 注意:如新表已存在,将会报错
2.102 修改表数据
# 格式:UPDATE 表名 SET 字段1=值1,字段2=值2,…,字段n=值n [WHERE 条件];
# 案例:
UPDATE student SET sex = ‘女’;
UPDATE student SET address = '北京女子职业技术学校家政班' WHERE address = '北京女子职业技术学校刺绣班';

# 注意:如果不加where 就会修改表中所有的数据
2.103 删除表数据
#格式:DELETE FROM 表名 [WHERE条件];
#格式:TRUNCATE TABLE 表名;

TRUNCATE语句删除后将重置自增列,表结构及其字段、约束、索引保持不变,执行速度比DELETE语句快

案例:

DELETE FROM student WHERE studentName = ‘王宝宝’;
TRUNCATE TABLE student;

####三,DQL(数据查询)语句

3.1 查询语法

SELECT <列名|表达式|函数|常量>

FROM <表名>

[where <查询条件表达式>]

[order by <排序的列名>[ASC或DESC]];

[LIMIT [位置偏移量,]行数];

注意:语法中 <>中的内容是必须的,[]中的内容不是必须要的,视情况而定

案例:查询gradeId = 1的数据并根据studentNo排序

SELECT `studentNo`,`studentName`,`phone`,`address`,`bornDate`
FROM `student`
WHERE `gradeId` = 1
ORDER BY `studentNo`;

查询全部的列:

# 格式:select * from 表名;
# 案例:select * from student;

查询部分列:

SELECT `studentNo`,`studentName`,`address`
FROM `student`
WHERE `address`=‘河南新乡’;
3.2 order by子句

order by子句实现按一定顺序显示查询结果

#案例:把成绩都降低10%后加5分,再查询及格成绩,并按照成绩从高到低排序
#参考代码
SELECT `studentNo` AS 学生编号,(studentResult*0.9+5 ) AS 综合成绩
FROM `result`
WHERE (`studentResult`*0.9+5) >=60
ORDER BY studentResult DESC;

#注意:order by 默认的是升序排列,如果需要降序就在order by字段后面加desc,升序排列可以在字段后面加asc
3.3 limit 子句:限制结果集显示条数
#案例:
#查询所有年级编号为1的学员信息,按学号升序排序
#每页4条,显示第2页,即从第5条记录开始显示4条数据
SELECT `studentNo`,`studentName`,`phone`,`address`,`bornDate`
FROM `student`
WHERE `gradeId` = 1
ORDER BY studentNo
LIMIT 4,4;
#注意:使用LIMIT子句时,注意第1条记录的位置是0!
3.4 子查询

案例一:

编写SQL语句,查看年龄比“李斯文”小的学生,要求显示这些学生的信息

分析:

第一步:查询得到“李斯文”的出生日期

SELECT `bornDate` FROM `student` WHERE `studentName` = '李斯文';

加入查询出来李斯文的出生日期是 1993-07-23

第二步:利用WHERE语句,筛选出生日期比“李斯文”大的学生

SELECT `studentNo`, `studentName`,`sex`,`bornDate`,`address` FROM `student` WHERE bornDate > '1993-07-23';

上面使用两步可以实现案例一的需求,同时我们也可以用子查询来解决这个问题:

SELECT studentNo,studentName,sex,bornDate,address FROM student

WHERE bornDate> (SELECT bornDate FROM student WHERE studentName=‘李斯文’);

子查询是一个嵌套在 SELECT、INSERT、UPDATE 或 DELETE 语句或其他子查询中的查询

子查询在WHERE语句中的一般用法:

SELECT … FROM 表1 WHERE 字段1 比较运算符(子查询)

将子查询和比较运算符联合使用,必须保证子查询返回的值不能多于一个

3.5查询数据-使用函数
3.5.1 聚合函数
函数名 作用
AVG() 返回某字段的平均值
COUNT() 返回某字段的行数
MAX() 返回某字段的最大值
MIN() 返回某字段的最小值
SUM() 返回某字段的和
3.5.2 字符串函数
函 数 名 作 用 举 例
CONCAT(str1, str1…strn) 字符串连接 SELECT CONCAT(‘My’,‘S’,‘QL’);返回:MySQL
INSERT(str,pos,len,newstr) 字符串替换 SELECT INSERT( ‘这是SQL Server数据库’, 3,10,‘MySQL’);返回:这是MySQL数据库
LOWER(str) 将字符串转为小写 SELECT LOWER(‘MySQL’);返回:mysql
UPPER(str) 将字符串转为大写 SELECT UPPER(‘MySQL’); 返回:MYSQL
SUBSTRING (str,num,len) 字符串截取 SELECT SUBSTRING( ‘JavaMySQLOracle’,5,5);返回:MySQL

######3.5.3 日期函数

函数名 作用 举例(结果与当前时间有关)
CURDATE() 获取当前日期 SELECT CURDATE();返回:系统当前日期
CURTIME() 获取当前时间 SELECT CURTIME();返回:系统当前时间
NOW() 获取当前日期和时间 SELECT NOW();返回:系统当前时间和日期
WEEK(date) 返回日期date为一年中的第几周 SELECT WEEK(NOW());
YEAR(date) 返回日期date的年份 SELECT YEAR(NOW());
HOUR(time) 返回时间time的小时值 SELECT HOUR(NOW());
MINUTE(time) 返回时间time的分钟值 SELECT MINUTE(NOW());
DATEDIFF(date1,date2) 返回日期参数date1和date2之间相隔的天数 SELECT DATEDIFF(NOW(), ‘2008-8-8’);
ADDDATE(date,n) 计算日期参数date加上n天后的日期 SELECT ADDDATE(NOW(),5);
3.5.4 数字函数
函数名 作 用 举 例
CEIL(x) 返回大于或等于数值x的最小整数 SELECT CEIL(2.3)返回:3
FLOOR(x) 返回小于或等于数值x的最大整数 SELECT FLOOR(2.3)返回:2
RAND() 返回0~1间的随机数 SELECT RAND()返回:0.5525468583708134
3.6 in 子查询
# 格式: select ... from 表名  where  字段 in (列表);
# 案例: 查询出分数为 60,95 ,71 分的学生编号,和分数
select studentNo ,studentResult from result
where studentResult=60 or studentResult=95 or studentResult=71;
# 使用in
select studentNo ,studentResult from result where studentResult in (60,95,71);

# 案例:查询出哪些同学的分数大于71分,显示出学生名称
# 步骤一,查询出分数大于71的学生编号
select studentNo from result where studentResult>71; -- (10002,10005,10096,10008)
# 步骤二,查出学生编号在步骤一的集合中的学生名称和编号
select studentNo,studentName from student where studentNo
in(select  studentNo from result where studentResult>71);

# 如果格式为: select ... from 表名 where 字段 in(子查询)
# in括号中为子查询时,子查询返回的列只能是一列,否则就会出错
# 比如:下面的in中的子查询,查询studentResult,studentNo 两列,执行语句时会报
#  Operand should contain 1 column(s) 错误
select studentNo,studentName from student where studentNo
in(select studentResult, studentNo from result where studentResult>71);

案例:查询参加“Logic Java”课程最近一次考试的在读学生名单

分析:

第一步:获得 “Logic Java”课程的课程编号

SELECT `subjectNo` FROM `subject` WHERE `subjectName`='Logic Java';

第二步:根据课程编号查询得到“Logic Java”课程最近一次的考试日期

SELECT MAX(`examDate`) FROM `result` WHERE `subjectNo`= (
SELECT `subjectNo` FROM `subject`
WHERE `subjectName`='Logic Java' );

第三步:根据课程编号和最近一次的考试日期查询出在读学生信息

SELECT `studentNo`, `studentName` FROM `student`
WHERE `studentNo IN (
SELECT `studentNo` FROM `result`
WHERE `subjectNo` IN (
SELECT `subjectNo` FROM `subject`
WHERE `subjectName`=' Logic Java'
) AND `examDate` = (
SELECT MAX(`examDate`) FROM `result`
WHERE `subjectNo` = (
SELECT `subjectNo` FROM `subject`
WHERE `subjectName`='Logic Java '
)
)
);

练习:查询“Logic Java”课程考试成绩为60分的学生名单

参考代码

SELECT `studentName` FROM `student`
WHERE `studentNo` IN(
SELECT `studentNo` FROM `result`
WHERE `subjectNo` =  (
SELECT `subjectNo` FROM `subject`
WHERE `subjectName`='Logic Java'
)AND `studentResult` = 60
);

常用IN替换等于(=)的子查询

IN后面的子查询可以返回多条记录

3.7 exists关键字

如何用SQL语句检测表是否创建?

drop table if exists 表名 ;

exists作用在子查询中

# 格式 select ... from 表名 where exists(子查询)
# 子查询有结果返回:exists(子查询)  结果为true
# 子查询没有结果返回: exists(子查询) 结果就为false,外层查询不执行
# 比如:判断是否有成绩大于80的数据
select exists(select*from result where studentResult>80);

# 案例:检查"Logic Java" 课程最近一次考试成绩
# 如果考试成绩有80分以上的成绩,显示分数排在前5名的学员学号和分数

# 分析:
# 采用exists 检测是否有人考试成绩达到了80分以上
# 如果有,使用select语句查询成绩从高到低排序,显示前5名的学号和成绩

# 第一步: 查询result表中所有Logic Java 的考试成绩
select * from result where subjectNo=(select subjectNo from subject where subjectName="Logic Java" );
# 第二步:查询出成绩大于80的数据
select * from result where subjectNo=(select subjectNo from subject where subjectName="Logic Java" ) and studentResult>80;

# 综合
select studentNo ,studentResult
from result where exists(
select * from result where subjectNo=(
select subjectNo from subject where subjectName="Logic Java" )
and studentResult>80 )
order by studentResult desc
limit 0,5;
3.8分组查询 group by
问题:查询出每门课的平均成绩
## 查询所有的平均成绩
select avg(studentResult) avgresult from result;

# 分组查询的格式
# select ... from 表名 where ... group by 分组字段;
# 表示根据某个字段进行分组
select subjectNo ,avg(studentResult) avgresult from result group by subjectNo;

# 练习1:查询出每门课的总成绩
# 练习2:分别统计每个年级的人数
select count(*) from student group by gradeId;

# 问题: 分别统计每个年级 男,女生人数
select gradeId 年级, sex 性别 ,count(*) 人数 from student group by gradeId ,sex;
# 注意:如果需要根据多个字段分组,可以将多个字段都加到group by后面,用逗号隔开

# 问题:查询出每门课的平均成绩,按照成绩从高到低排序
select subjectNo ,avg(studentResult) avgresult from result
group by subjectNo
order by avg(studentResult) desc;
3.9分组筛选
# 格式:select ... from 表名 where ... group by  ...  having...
# 问题:查询出平均成绩大于68分的的课程编号
# 步骤一:查询出每门课的平均成绩,及课程编号
select subjectNo ,avg(studentResult) avgresult from result group by subjectNo;
# 步骤二:筛选出平均成绩大于68分的课程编号
select subjectNo ,avg(studentResult) avgresult from result
group by subjectNo
having avg(studentResult)>68;
3.10 distinct 去重
# 问题: 查询出成绩表中有哪些课程的成绩,显示出课程名称
select subjectName from subject where subjectNo in (select subjectNo from result);

select subjectNo from result;
-- 此条查询语句,会查询出很多重复数据,这些重复数据在列表中,会影响查询性能,一般会选择去掉重复数据。

# distinct 关键字使用
# 格式: select distinct ...  from 表名;
select distinct subjectNo from result;
# 表示 查询subjectNo ,并去掉重复数据

select distinct subjectNo,studentResult from result
# 表示查询 subjectNO ,studentResult ,并去掉 重复的结果数据

# 注意:
# distinct 会将后面的字段值看做一个整体,只有当字段值都一样时才会认为是重复数据
# dustinct 只能卸载select 后面
# 比如下面写法会出错
select subjectNo , distinct studentResult from result;
3.11 like 关键字:模糊查询
# 问题: 查询出 姓李的学生数据
# 使用like模糊查询解决问题

# 格式 : select ... from 表名  where  字段 like ...
select * from student where studentName like '_斯_';
# 注意: 下划线 _  表示一个占位符,表示此处一个内容
# %表示此处可以有0个或者多个内容
select * from student where studentName like '李%';

#练习:查询出名字中包含 ‘文’ 字的学生数据
select * from student where studentName like '%文%';
3.12 关联查询
3.12.1 内连接 (inner join)
# 内连接格式:
# select ... from 表1  inner join 表2  on 关联字段关系

#查询出学号,学生成绩,以及课程名称
select result.studentNo ,result.studentResult,subject.subjectName
from result inner join subject on result.subjectNo = subject.subjectNo;

#使用别名
select rs.studentNo ,rs.studentResult ,sb.subjectName
from result rs  inner join subject sb  on  rs.subjectNo = sb.subjectNo;

# 注意: on 后面 写的是多表关联的字段

# 格式: select ... from 表1  , 表2 where  关联字段关系
select result.studentNo ,result.studentResult,subject.subjectName
from result,subject where result.subjectNo = subject.subjectNo;

# 练习:  查询出分数大于71 的学生姓名,和分数

select st.studentName ,rs.studentResult from student st
inner join result rs  on st.studentNo=rs.studentNo
where rs.studentResult >71 ;
# 注意:关联查询中,使用字段时,建议在字段前面都加上表名. ,表示区分使用的哪张表中的字段

# 练习:查询出分数大于71的学生姓名,分数,以及课程名称(三张表关联)
select st.studentName ,rs.studentResult ,sb.subjectName from student st
inner join result rs on st.studentNo=rs.studentNo
inner join subject sb on rs.subjectNo=sb.subjectNo
where rs.studentResult > 71;

#使用where 格式实现三张表关联
select st.studentName,rs.studentResult,sb.subjectName
from student st, result rs , subject sb
where st.studentNo= rs.studentNo and
rs.subjectNo = sb.subjectNo and
rs.studentResult > 71;
3.12.2 左外连接
# 格式: select ... from 表1  left join 表2 on ....
# 查询出每个学生姓名以及成绩
select st.studentName , rs.studentResult from student st
left join result rs  on st.studentNo = rs.studentNo;

查询结果

+-------------+---------------+

| studentName | studentResult |

+-------------+---------------+

| 郭靖        |            71 |

| 郭靖        |            60 |

| 李文        |            46 |

| 李斯文      |            83 |

| 张萍        |            60 |

| 韩秋洁      |            60 |

| 张秋丽      |            95 |

| 肖梅        |            93 |

| 秦洋        |            23 |

| 何睛睛      |            96 |

| 王宝宝      | NULL          |

| 何小华      | NULL          |

| 陈志强      | NULL          |

| 李露露      | NULL          |
+-------------+---------------+

将两张表位置互换

select st.studentName , rs.studentResult from  result rs
left join student st  on st.studentNo = rs.studentNo;

查询结果

+-------------+---------------+

| studentName | studentResult |

+-------------+---------------+

| 郭靖        |            71 |

| 郭靖        |            60 |

| 李文        |            46 |

| 李斯文      |            83 |

| 张萍        |            60 |

| 韩秋洁      |            60 |

| 张秋丽      |            95 |

| 肖梅        |            93 |

| 秦洋        |            23 |

| 何睛睛      |            96 |

+-------------+---------------+
# 对于left join而言
# left join 左边的表为主表  ,右边的表为从表
# 主表中的数据会逐条匹配从表中的数据
# 如果匹配到了数据,就显示数据
# 如果匹配不到,就用null填充

# 主表中的数据都会显示,
3.12.3 右外连接
# 对于right join而言
# right join 右边的表为主表  ,左边的表为从表
# 主表中的数据会逐条匹配从表中的数据
# 如果匹配到了数据,就显示数据
# 如果匹配不到,就用null填充

select st.studentName , rs.studentResult from  result rs
right join student st  on st.studentNo = rs.studentNo;

查询结果

+-------------+---------------+

| studentName | studentResult |

+-------------+---------------+

| 郭靖        |            71 |

| 郭靖        |            60 |

| 李文        |            46 |

| 李斯文      |            83 |

| 张萍        |            60 |

| 韩秋洁      |            60 |

| 张秋丽      |            95 |

| 肖梅        |            93 |

| 秦洋        |            23 |

| 何睛睛      |            96 |

| 王宝宝      | NULL          |

| 何小华      | NULL          |

| 陈志强      | NULL          |

| 李露露      | NULL          |

四,综合练习

4.1准备数据
/*
Navicat MySQL Data Transfer

Source Server         : study
Source Server Version : 50525
Source Host           : localhost:3306
Source Database       : wzry

Target Server Type    : MYSQL
Target Server Version : 50525
File Encoding         : 65001

Date: 2019-04-19 22:32:11
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `dept`
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` int(11) NOT NULL AUTO_INCREMENT,
`dname` varchar(20) DEFAULT NULL,
`location` varchar(20) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('10', '研发部', '北京');
INSERT INTO `dept` VALUES ('20', '财务部', '上海');
INSERT INTO `dept` VALUES ('30', '销售部', '武汉');
INSERT INTO `dept` VALUES ('40', '后勤部', '天津');

-- ----------------------------
-- Table structure for `emp`
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`empno` int(11) NOT NULL AUTO_INCREMENT,
`ename` varchar(20) DEFAULT NULL,
`job` varchar(20) DEFAULT NULL,
`salary` int(11) DEFAULT NULL,
`bouns` int(11) DEFAULT NULL,
`hirdate` date DEFAULT NULL,
`manager` int(11) DEFAULT NULL,
`deptno` int(11) DEFAULT NULL,
PRIMARY KEY (`empno`)
) ENGINE=InnoDB AUTO_INCREMENT=1011 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1001', '张无忌', 'Manager', '10000', '2000', '2009-06-17', '1005', '10');
INSERT INTO `emp` VALUES ('1002', '后羿', 'Analyst', '8000', '1000', '2012-04-10', '1001', '10');
INSERT INTO `emp` VALUES ('1003', '德玛西亚', 'Analyst', '9000', '1000', '2011-02-11', '1001', '10');
INSERT INTO `emp` VALUES ('1004', '刘备', 'Programmer', '5000', null, '2011-05-03', '1001', '10');
INSERT INTO `emp` VALUES ('1005', '徐凤年', 'President', '15000', null, '2008-07-03', null, '20');
INSERT INTO `emp` VALUES ('1006', '曹操', 'Manager', '5000', '400', '2009-02-01', '1005', '20');
INSERT INTO `emp` VALUES ('1007', '典韦', 'Clerk', '4000', '500', '2009-02-01', '1006', null);
INSERT INTO `emp` VALUES ('1008', '邓太阿', 'Manager', '5000', '800', '2009-03-01', '1005', '30');
INSERT INTO `emp` VALUES ('1009', '曹长卿', 'Salesman', '4000', null, '2011-05-03', '1008', '30');
INSERT INTO `emp` VALUES ('1010', '李淳罡', 'Salesman', '4500', null, '2011-05-03', '1008', '30');
4.2 完成如下练习

方法一:

1. 查询职员表中工资大于 5600 的员工姓名和工资
select emp.ename, emp.salary from emp where emp.salary>5600;
2. 查询职员表中员工号为 1008 的员工的姓名和部门号码
select emp.ename ,emp.salary from emp where emp.empno=1008;
3. 选择职员表中工资不在 6000 到 8000 的员工的姓名和工资
select emp.ename, emp.salary from emp where emp.salary>8000 and emp.salary<6000;
4. 选择职员表中在 20 和 30 号部门工作的员工姓名和部门号
select emp.ename, emp.deptno from emp where emp.deptno = 20 or emp.deptno = 30;
5. 选择职员表中没有管理者的员工姓名及职位, 按职位排序
select emp.ename,emp.job from emp where emp.manager is null order by emp.job;
6. 选择职员表中有奖金的员工姓名,工资和奖金,按工资倒序排列
select emp.ename,emp.salary ,emp.bouns from emp where emp.bouns>0 ORDER BY emp.salary desc;
7. 选择职员表中员工姓名的第二个字是 "长" 的员工姓名
select emp.ename from emp where emp.ename like "_长%";
8. 列出部门表中的部门名字和所在城市;
select dept.dname,dept.location from dept;
9. 显示出职员表中的不重复的职位;
select DISTINCT emp.job from emp ;
10. 查询职员表 emp 中员工号、姓名、工资,以及工资提高百分之 20%后的结果
select emp.empno,emp.ename,emp.salary,emp.salary*1.2 "加权工资" ,emp.job from emp ;
11. 查询员工的姓名和工资数,条件限定为工资数必须大于 7200,并对查询结果按入职时间进行排列,早入职排在前面,晚入职排在后面。
select emp.ename,emp.salary ,emp.hirdate from emp where emp.salary>7200 ORDER BY emp.hirdate;

方法二:

1.显示所有员工的姓名 ename,部门号 deptno 和部门名称 dname。
select emp.ename,emp.deptno,dept.dname from emp , dept where emp.deptno=dept.deptno;

2. 选择在 北京 工作的员工的员工姓名、职位、部门编码、部门名字
select emp.ename,emp.job,emp.deptno,dept.dname from emp , dept where emp.deptno=dept.deptno and dept.location="北京";
3. 选择所有员工的姓名 ename,员工号 deptno,以及他的管理者 mgr 的姓名 ename 和员工号deptno
select emp.ename , emp.empno from emp where emp.empno in(select emp.manager from emp);
4. 查询各部门员工姓名和他们所在位置,结果类似于下面的格式
select dept.dname,emp.ename,dept.location from emp inner JOIN dept on emp.deptno = emp.deptno GROUP BY dept.deptno
5. 查询出 邓太阿 的领导是谁(邓太阿 向谁报告)。
select * from emp where emp.empno = (select emp.manager from emp where emp.ename = "邓太阿");
6. 邓太阿 领导谁。(谁向 邓太阿 报告)。
select * from emp where emp.empno in (select emp.empno from emp where emp.manager =(select emp.empno from emp where emp.ename = "邓太阿"));
7. 查询和 曹长卿 相同部门的员工姓名 ename 和雇用日期 hiredate
select emp.ename,emp.hirdate from emp where emp.deptno=(select emp.deptno from emp where emp.ename="曹长卿");
8. 查询工资比公司平均工资高的所有员工的员工号 empno,姓名 ename 和工资 salary。
select emp.empno,emp.ename,emp.salary from emp where emp.salary> (select AVG(emp.salary ) "平均工资" from emp);
9. 查询和姓名中包含字母 曹 的员工在相同部门的员工的员工号 empno 和姓名 ename
select emp.empno,emp.ename from emp where emp.ename like "%曹%";

10. 查询在部门的 location 为 北京 的部门工作的员工的员工姓名 ename,部门名称 dname 和岗
位名称 job
select emp.ename ,dept.dname ,emp.job from emp ,dept where emp.deptno=dept.deptno and dept.location = "北京";
11. 查询管理者是 徐凤年 的员工姓名 ename 和工资 sal
select emp.ename,emp.salary from emp where emp.empno in (select emp.empno from emp where emp.manager =(select emp.empno from emp where emp.ename = "徐凤年"));
12. 显示 研发部 部门有哪些职位
select emp.job from emp where emp.deptno =( select dept.deptno from dept where dept.dname="研发部");
13. 各个部门中工资大于 5000 的员工人数
select  deptno,count(DISTINCT emp.empno) "各部门工资>5000" from emp where salary>5000 GROUP BY deptno ;
14. 哪些员工的工资,高于整个公司的平均工资,列出员工的名字和工资,降序排列
select emp.ename,emp.salary from emp where emp.salary> (select AVG(emp.salary ) "平均工资" from emp) order by emp.salary;
15. 所在部门平均工资高于 5000 的员工名字
select emp.ename from emp where emp.deptno in(select dno.deptno from (select emp.deptno ,AVG(emp.salary ) davg from emp GROUP BY emp.deptno HAVING davg>5000) dno );
16. 列出各个部门中工资最高的员工的信息:名字、部门号、工资
select emp.ename,emp.deptno,salary from emp ,(select emp.deptno dno, max(emp.salary) msal from emp group by emp.deptno) gbmzggz where emp.deptno=gbmzggz.dno and emp.salary=gbmzggz.msal ;
17. 哪个部门的平均工资是最高的,列出部门号、平均工资
select * from (select emp.deptno dno,AVG(emp.salary) sal from emp group by emp.deptno ) salavg where salavg.sal=(select max(sal) from (select emp.deptno ,AVG(emp.salary) sal from emp group by emp.deptno ) tmp);
-- 1. 查询职员表中工资大于 5600 的员工姓名和工资
SELECT ename AS 员工姓名,salary AS 工资 FROM emp WHERE salary>5600;

-- 2. 查询职员表中员工号为 1008 的员工的姓名和部门号码
SELECT ename AS 员工姓名,deptno AS 部门号码 FROM emp WHERE empno=1008;

-- 3. 选择职员表中工资不在 6000 到 8000 的员工的姓名和工资
SELECT ename AS 员工姓名,salary AS 工资 FROM emp WHERE salary<6000 OR salary>8000;

-- 4. 选择职员表中在 20 和 30 号部门工作的员工姓名和部门号
SELECT ename AS 员工姓名,deptno AS 部门号 FROM emp WHERE deptno IN(20,30);

-- 5. 选择职员表中有管理者的员工姓名及职位, 按职位排序
SELECT ename AS 员工姓名,job AS 职位 FROM emp WHERE manager IS NOT NULL ORDER BY job;

-- 6. 选择职员表中有奖金的员工姓名, 工资和奖金, 按工资倒序排列
SELECT ename AS 员工姓名,salary AS 工资,bouns AS 奖金 FROM emp WHERE bouns IS NOT NULL ORDER BY salary DESC;

-- 7. 选择职员表中员工姓名的第二个字是 "长" 的员工姓名
SELECT ename AS 员工姓名 FROM emp WHERE ename LIKE "_长%";

-- 8. 列出部门表中的部门名字和所在城市;
SELECT dname AS 部门名称,location AS 所在城市 FROM dept;

-- 9. 显示出职员表中的不重复的职位;
SELECT DISTINCT job AS 职位 FROM emp;

-- 10. 查询职员表 emp 中员工号、 姓名、 工资, 以及工资提高百分之 20%后的结果
SELECT empno AS 员工号,ename AS 姓名,salary AS 工资,salary*1.2 AS 涨后工资 FROM emp;

-- 11. 查询员工的姓名和工资数, 条件限定为工资数必须大于 7200, 并对查询结果按入职时间进行排列, 早入职排在前
-- 面, 晚入职排在后面。
SELECT ename AS 员工姓名,salary AS 工资 FROM emp WHERE salary>7200 ORDER BY hirdate;

-- --------------------------------------------------------------------------------------------
-- --------------------------------------------------------------------------------------------
-- --------------------------------------------------------------------------------------------

-- 1. 显示所有员工的姓名 ename, 部门号 deptno 和部门名称 dname。
SELECT e.ename AS 员工姓名,d.deptno AS 部门号,d.dname AS 部门名称 FROM emp AS e INNER JOIN dept AS d ON (d.deptno=e.deptno);

-- 2. 选择在 DALLAS 工作的员工的员工姓名、 职位、 部门编码、 部门名字
SELECT e.ename AS 员工姓名,e.job AS 职位,e.deptno AS 部门编号,d.dname AS 部门名称 FROM emp AS e INNER JOIN dept AS d ON (d.deptno=e.deptno) WHERE d.location="DALLAS";

-- 3. 选择所有员工的姓名 ename, 员工号 deptno, 以及他的管理者 mgr 的姓名 ename 和员工号deptno
SELECT e1.ename AS 员工姓名,e1.empno AS 员工编号,e2.ename AS 管理者姓名,e2.empno AS 管理者编号 FROM emp AS e1 INNER JOIN emp AS e2 ON(e1.manager=e2.empno);

-- 4. 查询各部门员工姓名和他们所在位置, 结果类似于下面的格式
SELECT d.dname AS 部门名称,e.ename AS 员工姓名,d.location AS 所在地 FROM emp AS e INNER JOIN dept AS d ON(d.deptno=e.deptno);

-- 5. 查询出 邓太阿 的领导是谁(邓太阿 向谁报告) 。
SELECT e2.ename AS 邓太阿的领导 FROM emp AS e2 INNER JOIN emp AS e1 ON (e1.manager=e2.empno) WHERE e1.ename="邓太阿";

-- 6. 邓太阿 领导谁。 (谁向 邓太阿 报告) 。
SELECT e1.ename AS 邓太阿领导的人 FROM emp AS e1 INNER JOIN emp AS e2 ON (e1.manager=e2.empno) WHERE e2.ename="邓太阿";

-- 7. 查询和 曹长卿 相同部门的员工姓名 ename 和雇用日 期 hiredate
SELECT ename AS 员工姓名,hirdate AS 雇用日期 FROM emp WHERE deptno in(SELECT deptno FROM emp WHERE ename="曹长卿") AND ename!="曹长卿";

-- 8. 查询工资比公司平均工资高的所有员工的员工号 empno, 姓名 ename 和工资 salary。
SELECT empno,ename,salary FROM emp WHERE salary>(SELECT AVG(salary) FROM emp);

-- 9. 查询和姓名中包含字母 曹 的员工在相同部门的员工的员工号 empno 和姓名 ename
SELECT empno,ename FROM emp WHERE deptno IN (SELECT deptno FROM emp WHERE ename LIKE "%曹%");

-- 10. 查询在部门的 location 为 北京 的部门工作的员工的员工姓名 ename, 部门名称 dname 和岗
-- 位名称 job
SELECT e.ename,d.dname,e.job FROM emp AS e INNER JOIN dept AS d ON (d.deptno=e.deptno) WHERE d.location="北京";

-- 11. 查询管理者是 徐凤年 的员工姓名 ename 和工资 sal
SELECT e1.ename,e1.salary FROM emp AS e1 INNER JOIN emp AS e2 ON (e1.manager=e2.empno) WHERE e2.ename="徐凤年";

-- 12. 显示 研发部 部门有哪些职位
SELECT DISTINCT emp.job AS 职位 FROM emp INNER JOIN dept ON (dept.deptno=emp.deptno) WHERE dept.dname="研发部";

-- 13. 各个部门中工资大于 5000 的员工人数
SELECT d.dname AS 部门名称,COUNT(*) AS 员工人数 FROM emp AS e INNER JOIN dept AS d ON (d.deptno=e.deptno) WHERE e.salary>5000 GROUP BY e.deptno;

-- 14. 哪些员工的工资, 高于整个公司的平均工资, 列出员工的名字和工资, 降序排列
SELECT ename,salary FROM emp WHERE salary>(SELECT AVG(salary) FROM emp) ORDER BY salary DESC;

-- 15. 所在部门平均工资高于 5000 的员工名字
SELECT ename FROM emp GROUP BY deptno HAVING AVG(salary)>5000;

-- 16. 列出各个部门中工资最高的员工的信息: 名字、 部门号、 工资
SELECT ename,deptno,salary FROM emp GROUP BY deptno HAVING salary=MAX(salary);

-- 17. 哪个部门的平均工资是最高的, 列出部门号、 平均工资
SELECT deptno,AVG(salary) AS 平均工资 FROM emp GROUP BY deptno ORDER BY AVG(salary) DESC LIMIT 1;
  • 点赞
  • 收藏
  • 分享
  • 文章举报
Dear_Gpk 发布了4 篇原创文章 · 获赞 1 · 访问量 877 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: