练习链接
1 查询所有数据
查询students表的所有数据
SELECT * FROM students;
SELECT可以用作计算,直接计算出表达式的结果,但它并不是SQL的强项。
但是不带FROM子句的SELECT语句,可用来判断当前到数据库的连接是否有效。
许多检测工具会执行一条SELECT 1,来测试数据库连接。
2 条件查询
1)查询分数在80分以上的学生记录。
SELECT * FROM students WHERE score >= 80;
2)符合条件“分数在80分或以上”,并且还符合条件“男生”
SELECT * FROM students WHERE score >= 80 AND gender = 'M';
3)符合条件“分数在80分或以上”或者“男生”
SELECT * FROM students WHERE score >= 80 OR gender = 'M';
4)符合条件“不是2班的学生”,NOT查询不是很常用
SELECT * FROM students WHERE NOT class_id = 2;
5)分数在80以下或者90以上,并且是男生
SELECT * FROM students WHERE (score < 80 OR score > 90) AND gender = 'M';
NOT优先级最高,其次是AND,最后是OR。加上括号可以改变优先级。
3 投影查询
1)只希望返回某些列的数据,而不是所有列的数;
例如,从students表中返回id、score和name这三列:
SELECT id, score, name FROM students;
2)还可以给每一列起个别名,这样,结果集的列名就可以与原表的列名不同。
例如,以下SELECT语句将列名score重命名为points,而id和name列名保持不变:
SELECT id, score points, name FROM students;
4 排序
查询结果集通常是按照id排序的,也就是根据主键排序。
1)加上ORDER BY子句,改为其他条件排序,例如按照成绩从低到高进行排序:
SELECT id, name, gender, score FROM students ORDER BY score;
2)如要反过来,按照成绩从高到底排序,末尾加上DESC表示“倒序”:
SELECT id, name, gender, score FROM students ORDER BY score DESC;
3)如果score列有相同数据,进一步排序,可以继续添加列名。
例如,使用ORDER BY score DESC, gender表示先按score列倒序,如果有相同分数的,再按gender列排序:
SELECT id, name, gender, score FROM students ORDER BY score DESC, gender;
4)有WHERE子句,ORDER BY要放到WHERE后。
例如,查询一班的学生成绩,并按照倒序排序:
SELECT id, name, gender, score
FROM students
WHERE class_id = 1
ORDER BY score DESC;
5 分页查询
SELECT查询时,如几万行数据,一个页面显示数据量太大,不如分页显示,每次显示100条。
步骤如下:
1)我们先把所有学生按照成绩从高到低进行排序:
SELECT id, name, gender, score FROM students ORDER BY score DESC;
2)把结果集分页,每页3条记录。
查询第1页记录,可以使用LIMIT 3 OFFSET 0:
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 0;
如果要查询第2页,需要“跳过”头3条记录。(每页记录条数* (页码 - 1))
也就是对结果集从3号记录开始查询,把OFFSET设定为3:
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 3;
如果原本记录集一共就10条记录,但我们把OFFSET设置为20,显示结果如下:
Empty result set
OFFSET超过了查询的最大数量并不会报错,而是得到一个空的结果集。
6 聚合查询
统计一张表的数据量,例如,想查询students表一共有多少条记录:
SELECT COUNT(*) FROM students;
通常,使用聚合查询时,我们应该给列名设置一个别名,便于处理结果:
SELECT COUNT(*) num FROM students;
除了COUNT()函数外,SQL还提供了如下聚合函数:
分组聚合
SQL还提供了“分组聚合”的功能,按class_id分组:
SELECT COUNT(*) num FROM students GROUP BY class_id;
可以把class_id列也放入结果集中,便于查看班级:
SELECT class_id, COUNT(*) num FROM students GROUP BY class_id;
聚合查询的列中,只能放入分组的列。
并没有按照name分类,以下报错:
SELECT name, class_id, COUNT(*) num FROM students GROUP BY class_id;
也可以使用多个列进行分组。
例如,我们想统计各班的男生和女生人数:
SELECT class_id, gender, COUNT(*) num FROM students GROUP BY class_id, gender;
7 多表查询
1) SELECT可以从多张表同时查询数据。
例如,同时从students表和classes表的“乘积”,又称笛卡尔查询:
SELECT * FROM students, classes;
以上为students表的每一行,与classes表的每一行,两两拼在一起返回。
结果集列数 = students列数 + classes列数
结果集行数 = students行数 * classes行数
2) 上述结果集有两列id和两列name,不好区分。
要解决这个问题,可以利用投影查询的“设置列的别名”来给两个表各自的id和name列起别名:
SELECT
students.id sid,
students.name,
students.gender,
students.score,
classes.id cid,
classes.name cname
FROM students, classes;
SQL还允许给表设置一个别名,让我们在投影查询中引用起来稍微简洁一点:
SELECT
s.id sid,
s.name,
s.gender,
s.score,
c.id cid,
c.name cname
FROM students s, classes c;
多表查询也是可以添加WHERE条件的,我们来试试:
SELECT
s.id sid,
s.name,
s.gender,
s.score,
c.id cid,
c.name cname
FROM students s, classes c
WHERE s.gender = 'M' AND c.id = 1;
8 连接查询
连接查询对多个表进行JOIN运算。
先确定一个主表作为结果集,然后把其他表的行,有选择性地“连接”在主表结果集上。
例如,我们想要选出students表的所有学生信息,可以用一条简单的SELECT语句完成:
SELECT s.id, s.name, s.class_id, s.gender, s.score FROM students s;
上面的结果集只有class_id列,缺少对应班级的name列。
存放班级名称的name列存储在classes表中,
需要根据students表的class_id,找到classes表对应的行的name列,就可得班级名称。
此时可通过 内连接——INNER JOIN来实现:
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
INNER JOIN classes c
ON s.class_id = c.id;
有内连接(INNER JOIN)就有外连接(OUTER JOIN)。
我们把内连接查询改成外连接查询:
SELECT s.id, s.name, s.class_id, c.name class_name, s.gender, s.score
FROM students s
RIGHT OUTER JOIN classes c
ON s.class_id = c.id;
效果如下:
多出来的一行“四班”,但是,学生相关的列如name、gender、score都为NULL。
这也容易理解,因为根据ON条件s.class_id = c.id,classes表的id=4的行正是“四班”,但是,students表中并不存在class_id=4的行。
此外有 LEFT OUTER JOIN,以及 FULL OUTER JOIN。它们的区别是:
1. INNER JOIN只返回同时存在于两张表的行数据。
由于students表的class_id包含1,2,3,classes表的id包含1,2,3,4,所以,INNER JOIN根据条件s.class_id = c.id返回的结果集仅包含1,2,3。
2. RIGHT OUTER JOIN返回右表都存在的行。
如果某一行仅在右表存在,那么结果集就会以NULL填充剩下的字段。
3. LEFT OUTER JOIN则返回左表都存在的行。
如果我们给students表增加一列,并添加class_id=5,由于classes表并不存在id=5的列,所以,LEFT OUTER JOIN的结果会增加一列,对应的class_name是NULL.
4. FULL OUTER JOIN,它会把两张表的所有记录全部选择出来。
并且,自动把对方不存在的列填充为NULL。