# 创建一个名为pet的表格 mysql>CREATETABLE pet ( -> name VARCHAR(20), -> owner VARCHAR(20), -> species VARCHAR(20), -> sex CHAR(1), -> birth DATE, -> death DATE -> );
-- 2.查询 student 表中的 name、sex 和 class 字段的所有行 SELECT name, sex, class FROM student;
-- 3.去重查询:查询 teacher 表中 department 列的不重复值 SELECTDISTINCT department FROM teacher;
-- 4.查询 score 表中成绩在60-80之间的所有行(区间查询和运算符查询) -- BETWEEN xx AND xx: 查询区间, AND 表示 "并且" SELECT*FROM score WHERE degree BETWEEN60AND80; SELECT*FROM score WHERE degree >60AND degree <80;
-- 5.查询 score 表中成绩为 85, 86 或 88 的行 -- IN: 查询规定中的多个值 SELECT*FROM score WHERE degree IN (85, 86, 88);
-- 6.查询 student 表中 '95031' 班或性别为 '女' 的所有行 -- or: 表示或者关系 SELECT*FROM student WHERE class ='95031'or sex ='女';
-- 7.以 class 降序的方式查询 student 表的所有行 -- DESC: 降序,从高到低 -- ASC(默认): 升序,从低到高 SELECT*FROM student ORDERBY class DESC; SELECT*FROM student ORDERBY class ASC;
-- AVG: 平均值 SELECTAVG(degree) FROM score WHERE c_no ='3-105'; SELECTAVG(degree) FROM score WHERE c_no ='3-245'; SELECTAVG(degree) FROM score WHERE c_no ='6-166';
-- GROUP BY: 分组查询 SELECT c_no, AVG(degree) FROM score GROUPBY c_no;
-- 课程表 SELECTno, name FROM course; +-------+-----------------+ |no| name | +-------+-----------------+ |3-105| 计算机导论 | |3-245| 操作系统 | |6-166| 数字电路 | |9-888| 高等数学 | +-------+-----------------+
-- 由于字段名存在重复,使用 "表名.字段名 as 别名" 代替。 SELECT student.name as s_name, course.name as c_name, degree FROM student, score, course WHERE student.NO = score.s_no AND score.c_no = course.no;
子查询加分组求平均分
查询 95031 班学生每门课程的平均成绩。
在 score 表中根据 student 表的学生编号筛选出学生的课堂号和成绩:
1 2 3 4 5 6 7 8 9 10 11 12 13
-- IN (..): 将筛选出的学生号当做 s_no 的条件查询 SELECT s_no, c_no, degree FROM score WHERE s_no IN (SELECTnoFROM student WHERE class ='95031'); +------+-------+--------+ | s_no | c_no | degree | +------+-------+--------+ |105|3-105|88| |105|3-245|75| |105|6-166|79| |109|3-105|76| |109|3-245|68| |109|6-166|81| +------+-------+--------+
这时只要将 c_no 分组一下就能得出 95031 班学生每门课的平均成绩:
1 2 3 4 5 6 7 8 9 10
SELECT c_no, AVG(degree) FROM score WHERE s_no IN (SELECTnoFROM student WHERE class ='95031') GROUPBY c_no; +-------+-------------+ | c_no |AVG(degree) | +-------+-------------+ |3-105|82.0000| |3-245|71.5000| |6-166|80.0000| +-------+-------------+
子查询 - 1
查询在 3-105 课程中,所有成绩高于 109 号同学的记录。
首先筛选出课堂号为 3-105 ,在找出所有成绩高于 109 号同学的的行。
1 2 3
SELECT*FROM score WHERE c_no ='3-105' AND degree > (SELECT degree FROM score WHERE s_no ='109'AND c_no ='3-105');
子查询 - 2
查询所有成绩高于 109 号同学的 3-105 课程成绩记录。
1 2 3
-- 不限制课程号,只要成绩大于109号同学的3-105课程成绩就可以。 SELECT*FROM score WHERE degree > (SELECT degree FROM score WHERE s_no ='109'AND c_no ='3-105');
YEAR 函数与带 IN 关键字查询
查询所有和 101 、108 号学生同年出生的 no 、name 、birthday 列。
1 2 3
-- YEAR(..): 取出日期中的年份 SELECTno, name, birthday FROM student WHEREYEAR(birthday) IN (SELECTYEAR(birthday) FROM student WHEREnoIN (101, 108));
多层嵌套子查询
查询 '张旭' 教师任课的学生成绩表。
首先找到教师编号:
1
SELECTNOFROM teacher WHERE NAME ='张旭'
通过 sourse 表找到该教师课程号:
1
SELECTNOFROM course WHERE t_no = ( SELECTNOFROM teacher WHERE NAME ='张旭' );
通过筛选出的课程号查询成绩表:
1 2 3 4 5
SELECT*FROM score WHERE c_no = ( SELECTnoFROM course WHERE t_no = ( SELECTnoFROM teacher WHERE NAME ='张旭' ) );
多表查询
查询某选修课程多于5个同学的教师姓名。
首先在 teacher 表中,根据 no 字段来判断该教师的同一门课程是否有至少5名学员选修:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
-- 查询 teacher 表 SELECTno, name FROM teacher; +-----+--------+ |no| name | +-----+--------+ |804| 李诚 | |825| 王萍 | |831| 刘冰 | |856| 张旭 | +-----+--------+
SELECT name FROM teacher WHEREnoIN ( -- 在这里找到对应的条件 );
-- 通过 teacher 表查询所有 `计算机系` 的教师编号 SELECTno, name, department FROM teacher WHERE department ='计算机系' +-----+--------+--------------+ |no| name | department | +-----+--------+--------------+ |804| 李诚 | 计算机系 | |825| 王萍 | 计算机系 | +-----+--------+--------------+
-- 通过 course 表查询该教师的课程编号 SELECTnoFROM course WHERE t_no IN ( SELECTnoFROM teacher WHERE department ='计算机系' ); +-------+ |no| +-------+ |3-245| |3-105| +-------+
-- 根据筛选出来的课程号查询成绩表 SELECT*FROM score WHERE c_no IN ( SELECTnoFROM course WHERE t_no IN ( SELECTnoFROM teacher WHERE department ='计算机系' ) ); +------+-------+--------+ | s_no | c_no | degree | +------+-------+--------+ |103|3-245|86| |105|3-245|75| |109|3-245|68| |101|3-105|90| |102|3-105|91| |103|3-105|92| |104|3-105|89| |105|3-105|88| |109|3-105|76| +------+-------+--------+
UNION 和 NOTIN 的使用
查询 计算机系 与 电子工程系 中的不同职称的教师。
1 2 3 4 5 6 7 8 9
-- NOT: 代表逻辑非 SELECT*FROM teacher WHERE department ='计算机系'AND profession NOTIN ( SELECT profession FROM teacher WHERE department ='电子工程系' ) -- 合并两个集 UNION SELECT*FROM teacher WHERE department ='电子工程系'AND profession NOTIN ( SELECT profession FROM teacher WHERE department ='计算机系' );
-- 只查询性别为男,然后按 class 分组,并限制 class 行大于 1。 SELECT class FROM student WHERE sex ='男'GROUPBY class HAVINGCOUNT(*) >1; +-------+ | class | +-------+ |95033| |95031| +-------+
SELECT*FROM course WHERE t_no in (SELECTnoFROM teacher WHERE sex ='男'); +-------+--------------+------+ |no| name | t_no | +-------+--------------+------+ |3-245| 操作系统 |804| |6-166| 数字电路 |856| +-------+--------------+------+
MAX 函数与子查询
查询最高分同学的 score 表。
1 2 3 4 5 6 7 8 9 10 11
-- 找出最高成绩(该查询只能有一个结果) SELECTMAX(degree) FROM score;
-- 首先将李军的性别作为条件取出来 SELECT sex FROM student WHERE name ='李军'; +-----+ | sex | +-----+ | 男 | +-----+
-- 根据性别查询 name 和 sex SELECT name, sex FROM student WHERE sex = ( SELECT sex FROM student WHERE name ='李军' ); +-----------+-----+ | name | sex | +-----------+-----+ | 曾华 | 男 | | 匡明 | 男 | | 李军 | 男 | | 陆军 | 男 | | 王尼玛 | 男 | | 张全蛋 | 男 | | 赵铁柱 | 男 | | 张飞 | 男 | +-----------+-----+
子查询 - 7
查询和 “李军” 同性别且同班的同学 name 。
1 2 3 4 5 6 7 8 9 10 11 12
SELECT name, sex, class FROM student WHERE sex = ( SELECT sex FROM student WHERE name ='李军' ) AND class = ( SELECT class FROM student WHERE name ='李军' ); +-----------+-----+-------+ | name | sex | class | +-----------+-----+-------+ | 曾华 | 男 |95033| | 李军 | 男 |95033| | 王尼玛 | 男 |95033| +-----------+-----+-------+
SELECT*FROM grade; +------+------+-------+ | low | upp | grade | +------+------+-------+ |90|100| A | |80|89| B | |70|79| C | |60|69| D | |0|59| E | +------+------+-------+
查询所有学生的 s_no 、c_no 和 grade 列。
思路是,使用区间 ( BETWEEN ) 查询,判断学生的成绩 ( degree ) 在 grade 表的 low 和 upp 之间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
SELECT s_no, c_no, grade FROM score, grade WHERE degree BETWEEN low AND upp; +------+-------+-------+ | s_no | c_no | grade | +------+-------+-------+ |101|3-105| A | |102|3-105| A | |103|3-105| A | |103|3-245| B | |103|6-166| B | |104|3-105| B | |105|3-105| B | |105|3-245| C | |105|6-166| C | |109|3-105| C | |109|3-245| D | |109|6-166| B | +------+-------+-------+
-- INNER JOIN: 表示为内连接,将两张表拼接在一起。 -- on: 表示要执行某个条件。 SELECT*FROM person INNERJOIN card on person.cardId = card.id; +------+--------+--------+------+-----------+ | id | name | cardId | id | name | +------+--------+--------+------+-----------+ |1| 张三 |1|1| 饭卡 | |2| 李四 |3|3| 农行卡 | +------+--------+--------+------+-----------+
-- 将 INNER 关键字省略掉,结果也是一样的。 -- SELECT * FROM person JOIN card on person.cardId = card.id;
注意:card 的整张表被连接到了右边。
左外连接
完整显示左边的表 ( person ) ,右边的表如果符合条件就显示,不符合则补 NULL 。
1 2 3 4 5 6 7 8 9
-- LEFT JOIN 也叫做 LEFT OUTER JOIN,用这两种方式的查询结果是一样的。 SELECT*FROM person LEFTJOIN card on person.cardId = card.id; +------+--------+--------+------+-----------+ | id | name | cardId | id | name | +------+--------+--------+------+-----------+ |1| 张三 |1|1| 饭卡 | |2| 李四 |3|3| 农行卡 | |3| 王五 |6|NULL|NULL| +------+--------+--------+------+-----------+
右外链接
完整显示右边的表 ( card ) ,左边的表如果符合条件就显示,不符合则补 NULL 。
1 2 3 4 5 6 7 8 9 10
SELECT*FROM person RIGHTJOIN card on person.cardId = card.id; +------+--------+--------+------+-----------+ | id | name | cardId | id | name | +------+--------+--------+------+-----------+ |1| 张三 |1|1| 饭卡 | |2| 李四 |3|3| 农行卡 | |NULL|NULL|NULL|2| 建行卡 | |NULL|NULL|NULL|4| 工商卡 | |NULL|NULL|NULL|5| 邮政卡 | +------+--------+--------+------+-----------+
全外链接
完整显示两张表的全部数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
-- MySQL 不支持这种语法的全外连接 -- SELECT * FROM person FULL JOIN card on person.cardId = card.id; -- 出现错误: -- ERROR 1054 (42S22): Unknown column 'person.cardId' in 'on clause'
-- MySQL全连接语法,使用 UNION 将两张表合并在一起。 SELECT*FROM person LEFTJOIN card on person.cardId = card.id UNION SELECT*FROM person RIGHTJOIN card on person.cardId = card.id; +------+--------+--------+------+-----------+ | id | name | cardId | id | name | +------+--------+--------+------+-----------+ |1| 张三 |1|1| 饭卡 | |2| 李四 |3|3| 农行卡 | |3| 王五 |6|NULL|NULL| |NULL|NULL|NULL|2| 建行卡 | |NULL|NULL|NULL|4| 工商卡 | |NULL|NULL|NULL|5| 邮政卡 | +------+--------+--------+------+-----------+
事务
在 MySQL 中,事务其实是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性。
比如我们的银行转账:
1 2 3 4 5
-- a -> -100 UPDATEuserset money = money -100WHERE name ='a';
-- b -> +100 UPDATEuserset money = money +100WHERE name ='b';