-- 进行查询练习的准备工作
CREATE TABLE exam_result (
id INT,
name VARCHAR(20),
chinese DECIMAL(3, 1),
math DECIMAL(3, 1),
english DECIMAL(3, 1)
);
INSERT INTO exam_result VALUES
(1,'唐三藏', 67, 98, 56),
(2,'孙悟空', 87.5, 78, 77),
(3,'猪悟能', 88, 98, 90),
(4,'曹孟德', 82, 84, 67),
(5,'刘玄德', 55.5, 85, 45),
(6,'孙权', 70, 73, 78.5),
(7,'宋公明', 75, 65, 30);
-- 全字段查询
-- * 代表给出表中的所有字段,顺序按照建表时的顺序给出
-- 没有给出 WHERE 条件,代表所有行都满足条件,查出所有行
-- 表中有什么数据,显示什么数据
-- 不推荐大家直接这么用,这么用有几个缺点:
-- 1. * 会展示所有字段,实践中往往只查询需要的字段,性能比较好
-- 2. 没有 WHERE 条件 并且一张表中数据量比较大时(千万级:一张表中有几千万条记录)
-- 会导致查询特别慢,类似卡死的情况都会出现
SELECT * FROM exam_result;
-- 指定字段查询,顺序无要求
SELECT id, name FROM exam_result;
SELECT name, id FROM exam_result;
-- 实际上,SELECT 后的投影可以是 任意表达式
-- 表达式中可以有字段的参与,也可以没有
SELECT id + 10, id FROM exam_result;
-- 表达式中没有字段的参与,也可以
SELECT 10, id FROM exam_result;
-- 一共有多少条记录,按照 WHERE 条件规则
-- 现在没有 WHERE 条件,是返回表中所有的记录,一共 7 条
SELECT 10 FROM exam_result;
-- 含义:查询每位同学的总分,包含多字段的表达式
SELECT id, name, math + chinese + english FROM exam_result;
-- 表达式中可以出现函数(不是重点,不展开说了)
-- concat 函数就是字符串拼接,类似 java 中的 name + " 你好"
SELECT id, concat(name, " 你好") FROM exam_result;
-- 特殊的查询:
-- 1. 投影里使用了函数 database()
-- 2. 没有指定查询源,视为从系统当前状态查询,只支持几个默认的函数
-- 只返回一行数据
SELECT DATABASE();
SELECT 1;
-- 为显示结果添加别名(alias) AS
SELECT id, name, math + chinese + english AS total FROM exam_result;
SELECT id, name, math + chinese + english AS 总分 FROM exam_result;
SELECT id, name, math + chinese + english 总分 FROM exam_result;
SELECT id 学号, name 姓名, math + chinese + english 总分 FROM exam_result;
-- 别名用中文没问题,但要求不要让库、表、字段名用中文
-- 可以用,但不推荐用,否则以后写代码的时候,很容易出现字符集问题
-- 显示 7 行 10
SELECT 10 FROM exam_result;
-- 合并重复项(DISTINCT)
SELECT DISTINCT 10 FROM exam_result;
SELECT math FROM exam_result;
SELECT DISTINCT math FROM exam_result;
SELECT name, math FROM exam_result;
-- 无法合并
-- SELECT name, DISTINCT math FROM exam_result;
-- 统计行数的函数 COUNT(...)
-- 得到的是 一个 数,本来有的结果的行数,Null 不被看作是一条记录
-- 等价 前提:math NOT NULL
SELECT COUNT(*) FROM exam_result; -- SELECT * FROM exam_result 的行数
SELECT COUNT(math) FROM exam_result; -- SELECT math FROM exam_result 中不是 Null 的行数
SELECT COUNT(1) FROM exam_result; -- SELECT 1 FROM exam_result; 的行数
SELECT COUNT(1) FROM exam_result WHERE id > 1 AND id < 5;
SELECT COUNT(NULL) FROM exam_result; -- 0
SELECT NULL FROM exam_result; -- 7 个 Null
SELECT COUNT(email) FROM students; -- Null COUNT(email) 不算 email 是 Null 的情况
SELECT COUNT(DISTINCT math) FROM exam_result; -- 去重后的数量
-- 排序
-- 强调:如果带上 ORDER BY,查询结果应该视为没有确定的顺序
-- 没有 order by,简单地认为结果无序即可
SELECT * FROM exam_result; -- 没有 order by,看起来结果是按照 id 的顺序给出
-- 但 MySQL 其实没有任何的保证,只是这个版本的 MySQL 刚好这么实现了
-- 以后改了也有可能
SELECT * FROM exam_result ORDER BY id; -- 明确结果的排序
-- order by 重点在 order 不在于 by
-- by 按照
-- order 排序
-- order by 按照 某某字段(表达式)的值进行排序
-- 从小到大(升序、非降序) 默认 ASC
-- 从大大小(降序、非升序) DESC
SELECT * FROM exam_result ORDER BY id; -- 按照 id 的顺序,升序给出
SELECT * FROM exam_result ORDER BY id ASC; -- 按照 id 的顺序,升序给出
SELECT * FROM exam_result ORDER BY id DESC; -- 按照 id 的顺序,降序给出
SELECT * FROM exam_result ORDER BY math;
SELECT * FROM exam_result ORDER BY math, id;
SELECT * FROM exam_result ORDER BY math ASC, id DESC;
SELECT * FROM exam_result ORDER BY math DESC, id ASC;
SELECT
*
FROM exam_result
ORDER BY math + chinese + english DESC;
SELECT
id, name, math + chinese + english total
FROM exam_result
ORDER BY math + chinese + english DESC, id;
SELECT
id, name, math + chinese + english total
FROM exam_result
ORDER BY total DESC, id; -- order by 跟别名
-- WHERE 条件,由 bool 表达式组成,把每条记录带入,根据结果进行选择,保留结果是 true 的
-- 简单
-- a > b a >= b a < b a <= b
SELECT 1 < 2; -- 真 1
SELECT 1 > 2; -- 假 0
SELECT 1 >= 2; -- 假 0
SELECT 1 <= 2; -- 真 1
SELECT * FROM exam_result WHERE id < 3;
SELECT id, name, id < 3 FROM exam_result;
-- 和 java 略有不同的
-- 相等使用一个 = 判断
-- a = b 不用 a == b
-- 无论是数值类型还是其他类型,都是用 = 进行相等判断
SELECT '你好' = '你好'; -- 真
SELECT 1 = 1; -- 真
SELECT '你好' = '世界'; -- 假
SELECT 1 = 2; -- 假
SELECT * FROM exam_result WHERE name = '猪悟能';
-- 不相等 !=、<>
-- a != b a <> b
SELECT '你好' != '你好'; -- 假
SELECT 1 != 1; -- 假
SELECT '你好' != '世界'; -- 真
SELECT 1 != 2; -- 真
SELECT '你好' <> '你好'; -- 假
SELECT 1 <> 1; -- 假
SELECT '你好' <> '世界'; -- 真
SELECT 1 <> 2; -- 真
SELECT * FROM exam_result WHERE name != '猪悟能';
-- 针对 Null 的判断,不能用相等判断,必须用特殊方法
-- a IS NULL a 为 null 时是 true
-- a IS NOT NULL a 不为 null 时是 true
-- MySQL 针对 Null 提出了特殊的表达式
-- a <=> b 判断 a 是否等于 b,并且支持 a b 都是 Null 的情况
SELECT 1 = 1; -- 真
-- Null 对于某个数据我们不知道
-- 与 Null 参与的表达式运算(暂时不考虑特例),结果也是 Null
-- 有不知道的值参与的表达式,结果还是不知道
SELECT NULL = NULL; -- 假,Null 又被视为假
SELECT NULL IS NULL; -- 真
SELECT NULL IS NOT NULL; -- 假
SELECT 1 IS NULL; -- 假
SELECT 1 IS NOT NULL; -- 真
SELECT name, email, email = NULL FROM students;
SELECT name, email, email != NULL FROM students;
SELECT name, email FROM students WHERE email = NULL; -- 没有符合条件的结果
SELECT name, email FROM students WHERE email != NULL; -- 没有符合条件的结果
SELECT name, email FROM students WHERE email IS NULL;
SELECT name, email FROM students WHERE email IS NOT NULL;
-- 不太推荐使用 <=> 这个表达式,更推荐使用 IS NULL 和 IS NOT NULL
SELECT 1 <=> 1; -- 真
SELECT 1 <=> 2; -- 假
SELECT 1 <=> NULL; -- 假
SELECT NULL <=> NULL; -- 真
-- 与 AND 不用 &&
-- 或 OR 不用 ||
-- 非 NOT 不用 !
SELECT 1 AND 1; --真
SELECT 1 AND 0; --假
SELECT 0 AND 1; --假
SELECT 0 AND 0; --假
SELECT 1 OR 1; --真
SELECT 1 OR 0; --真
SELECT 0 OR 1; --真
SELECT 0 OR 0; --假
SELECT !0; --真
SELECT !1; --假
找到成绩不及格的同学
--语文<60 或
--数学<60 或
--英语<60
SELECT * FROM students WHERE chinese <60 OR math<60 OR english <60;
--找到三好学生,每门课成绩都至少>=80
SELECT * FROM students WHERE chinese >=80 OR math>=80 OR english >=80;
-- a BETWEEN 10 AND 20
-- a >= 10 AND a <= 20 为 真
SELECT 10 BETWEEN 10 AND 20; --真
SELECT 9 BETWEEN 10 AND 20; --假
-- a IN ('AA', 'BB', 'CC')
-- a == 'AA' OR a == 'BB' OR a == 'CC'
--contains 包含关系
--前面的元素不在后面集合中
SELECT '你好' IN('你好','世界');
SELECT '你好' ='你好' OR '你好'='世界'; --手动遍历查找,确定包含关系
--所以建议使用IN
--上面包含留有空间,允许MySQL 自有发挥实现查找;
--下面的操作,明确使用遍历方式
------------------------------------------------------
--LIKE 做字符串的模糊匹配
--_代表名字是 孙开头,并且有三个字符,但后边是什么都行
SELECT * FROM students WHERE name LIKE '孙_';
--% 代表是任意(>=0)个字符
SELECT * FROM students WHERE name LIKE '孙%';
SELECT '孙' LIKE '%孙%' ;--只要带孙都行