查询语句知识点汇总

  • 一、基础查询
  • 二、条件查询
  • 三、排序查询
  • 四、常见函数
    • 4.1 单行函数
      • 4.1.1 字符函数
      • 4.1.2 数学函数
      • 4.1.3 日期函数
      • 4.1.4 其他函数
      • 4.1.5 流程控制函数
    • 4.2 分组函数 (也称为聚合函数/统计函数/组函数)
  • 五、分组查询
  • 六、连接查询(多表查询)
    • 6.1 笛卡尔乘积现象
    • 6.2 连接查询的分类
      • 6.2.1 sql92标准语法
      • 6.2.2 sql99标准语法
  • 七、子查询
    • 7.1 where或having后面
    • 7.2 select后面
    • 7.3 from后面
    • 7.4 exists后面(相关子查询)
  • 八、分页查询
  • 九、联合查询

一、基础查询

基本语法为:

SELECT 查询列表 FROM 表名

其中,查询列表可以是:表中字段、常量值、表达式、函数;查询的结果是一个虚拟的表格。

一些小tips:
1.可以用着重号 ''来区分字段和关键字
2.经常会使用DISTINCT 去重
3.起别名:既可以使用as,也可以使用空格

# 使用as起别名
SELECT * FROM employees AS e;
# 使用空格起别名
SELECT * FROM employees e;

4.+的作用:运算符

  • 两个操作数都为数值型,则做加法运算
  • 若其中一方为字符型,则尝试将字符型数值转换成数值型,转换成功则继续做运算,失败则转换为0
  • 只要一方为null,结果肯定为null

二、条件查询

SELECT 查询列表    第③步
FROM 表名        第①步
WHERE 筛选条件     第②步

筛选条件分类:

  • 按条件表达式筛选:=、!=、<>、<=、>=、<、>
  • 按逻辑表达式筛选:&&(and) 、||(or)、!(not)
  • 模糊查询:
    • like:通常搭配通配符(%代表任意多个字符,包含0个字符;_代表任意单个字符)
    • between and :包含临界值
    • in :列表内的值类型必须一致或兼容
    • is null、is not null
# 查询名字中带字母a的员工的所有信息
SELECT * FROM employees
WHERE last_name LIKE '%a%';# 查询员工名中第二个字符为_的员工名
SELECT last_name FROM employees
WHERE last_name LIKE '_\_%';   # 这里的\起到的是转义的作用

三、排序查询

SELECT 查询列表      第③步
FROM 表名           第①步
[WHERE 筛选条件]     第②步
ORDER BY 排序列表 [DESC/ASC]   第④步

特点:
1.默认asc升序排列
2.order by 支持单个字段、多个字段、表达式、别名、函数
3.order by一般放在查询语句的最后面,LIMIT子句除外

四、常见函数

需要掌握函数名、函数功能以及具有使用方法。

4.1 单行函数

4.1.1 字符函数

  1. length():获取参数值的字节个数
    值得注意的是,该函数获取的是字节的个数;utf8下一个英文字母占1个字节,一个汉字占3个字节;gbk下一个汉字占2个字节
SELECT LENGTH('MySQL');
# 5# 查看字符集
SHOW VARIABLES LIKE ‘%char%’;# 若客户端的字符集为utf8
SELECT LENGTH('数据库');
# 9
  1. concat(str1, str2, …) :拼接
# 将员工的first_name和last_name用‘_’进行连接
SELECT CONCAT('first_name','_','last_name') output
FROM employees;
  1. upper()/lower():将字符串中的小/大写全转换成大/小写
SELECT UPPER('mysQL') output;
# MYSQL
SELECT LOWER('MYSQL') output;
# mysql
  1. substr/substring(str,起始索引,截取长度):截取指定索引下的字符
    这里,有一点需要注意一下:索引是从1开始的
SELECT SUBSTR('查询语句知识点汇总',1,4) output;
# 查询语句
SELECT SUBSTR('查询语句知识点汇总',8) output;
# 汇总
  1. instr(str1,str2):返回子串第一次出现的索引,如果找不到,返回0
SELECT INSTR('查询语句知识点汇总','汇总') output;
# 7
  1. trim():去除前后空格,也可去除指定字符
SELECT TRIM('a' from '   数据库  ') output;
# 数据库
SELECT TRIM('a' from 'aaaa数aaaa据库aaaa') output;
# 数aaaa据库
SELECT TRIM('a' from 'aaaa数aaaa据库AAAAA') output;
# 数aaaa据库AAAAA
  1. lpad(str,指定长度,指定字符):用指定的字符实现左填充,使填充后的字符串达到指定长度,rpad同理
SELECT LPAD('数',3,'*') output;
# 数**
SELECT LPAD('数据库',2,'*') output;
# 数据
  1. replace(str,需要被替换的字符串,替换的字符串):替换
SELECT REPLACE('我爱学习','学习','看电视') output;
# 我爱看电视

4.1.2 数学函数

  1. rand():获取随机数,返回0-1之间的小数
SELECT RAND();
# 0.36748154868137234
  1. round():四舍五入
# 保留两位小数
SELECT ROUND(1.567, 2);
# 1.57
  1. ceil():向上取整,返回>=该参数的最小整数
    floor():向下取整,返回<=该参数的最大整数
# 在0-99间随机抽取一个整数
SELECT FLOOR(RAND()* 100);
# 在1-100间随机抽取一个整数
SELECT CEIL(RAND()* 100);
  1. truncate():截断
SELECT TRUNCATE(1.699999,1);
# 1.6
  1. mod(a, b):取余;a为被除数,b为除数。等价于%
    mod(a, b) = a - a/b*b
SELECT mod(10,3);
# 1
SELECT mod(-10,-3);    # -10-(-10)/(-3)*(-3) = -1
# -1
SELECT mod(10,-3);     # 10-(10)/(-3)*(-3) = 1
# 1

4.1.3 日期函数

  1. now(): 返回当前系统的日期+时间
  2. curdate(): 返回当前系统的日期,不包含时间
  3. curtime(): 返回当前时间
SELECT NOW();
# 2020-08-05T08:32:45Z
SELECT CURDATE();
# 2020-08-05
SELECT CURTIME();
# 08:35:20
  1. year()/month()/day()/hour()/minute()/second():获取指定部分的年/月/日/小时/分钟/秒
SELECT MONTH(NOW()) 月;
# 8
SELECT MONTHNAME(NOW()) 月;   #monthname以英文的形式返回月
# August
  1. str_to_date(): 将日期格式的字符转换成指定格式的日期
    (字符串转换成日期)
SELECT STR_TO_DATE('8-20-2050','%m-%d-%Y');
# 2050-08-20
  1. date_format(): 将日期按指定的格式转换成字符
    (日期转换成字符串)
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') output;
# 20年08月05日
SELECT DATE_FORMAT(NOW(),'%Y-%m-%d') output;
# 2020-08-05
  1. datediff(date1, date2): 计算两个日期之间的天数
    其中,datediff()函数对时间差值的计算方式为date1-date2
SELECT DATEDIFF('2020-06-05','2020-08-05') output;
# -61

4.1.4 其他函数

  1. version(): 查看MySQL的版本类型,等价于SHOW VARIABLES LIKE 'VERSION';
  2. database(): 查看当前所使用的数据库
  3. user(): 查看当前登录的用户

4.1.5 流程控制函数

  1. if 函数
SELECT IF(10>5, '大', '小');
# 大
  1. case 函数
    case可以搭配select充当表达式,也可以单独作为语句。
  • 等值判断
CASE 要判断的字段或表达式
WHEN 常量1 THEN 要显示的值1或语句1
WHEN 常量2 THEN 要显示的值2或语句2
......
[ELSE 要显示的值n或语句n]  <--- 可省略
END

【例】

SELECT salary 原始工资, department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END 新工资
FROM employees;
  • 区间判断
CASE
WHEN 条件1 THEN 要显示的值1或语句1
WHEN 条件2 THEN 要显示的值2或语句2
......
ELSE 要显示的值n或语句n
END

【例】

CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 70 THEN '良好'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END

4.2 分组函数 (也称为聚合函数/统计函数/组函数)

sum() avg() max() min() count()
求和 求平均 求最大值 求最小值 统计个数

特点:

  1. sum()、avg()一般用于处理数值型;而max()、min()、count()可处理任何类型
  2. 以上5个函数都忽略null值
  3. 均可以与distinct搭配使用
  4. 统计总行数:SELECT COUNT(*) FROM table1;或者SELECT COUNT(常量值,一般为1) FROM table1;
  5. 和分组函数一同查询的字段有限制:和分组函数一同查询的字段要求是group by后的字段

五、分组查询

SELECT 分组函数, 列(要求出现在group by的后面)   第④步
FROM 表名           第①步
[WHERE 筛选条件]     第②步
GROUP BY 需要分组的列  第③步
[ORDER BY子句]   第⑤步

特点:

  1. 分组查询中的筛选条件分为两类
数据源 位置 关键字
分组前筛选 原始表 group by前 where
分组后筛选 分组后的结果集 group by后 having
  • 分组函数条件肯定是放在having子句中
  • 能用分组前筛选的尽量在分组前筛
  1. group by子句支持单个、多个字段分段(逗号隔开,没有顺序)

六、连接查询(多表查询)

6.1 笛卡尔乘积现象

当查询的字段来自于多个表时,就会用到连接查询。

当表与表之间没有建立有效的连接条件时,就会出现笛卡尔乘积现象,即表1m行,表2n行,结果将产生一个么m*n行的表。

下面举个例子,大家来直观地感受一下笛卡尔乘积现象。

假设有两张表,具体如下:

表6.1: 人物表authors

id author_name sex born_date book_id
1 林徽因 1904-6 2
2 杨绛 1911-7 1

表6.2: 作品表books

id book_name publishing_date
1 干校六记 1981
2 你是人间四月天 2005

现在想要查询作者及其作品名,我们期望得到的是:

author_name book_name
林徽因 你是人间四月天
杨绛 干校六记

但如果直接使用SELECT author_name, book_name FROM authors,books;对两个表进行查询,就相当于拿着表1的每一行记录去依次匹配表2的每一行记录,则会得到:

author_name book_name
林徽因 你是人间四月天
林徽因 干校六记
杨绛 你是人间四月天
杨绛 干校六记

结果显然与实际不符,这就是一个典型的笛卡尔乘积错误现象。

6.2 连接查询的分类

按功能分类:

  • 内连接:等值连接、非等值连接、自连接
  • 外连接:左外连接、右外连接、全外连接(MySQL不支持)
  • 交叉连接

按年代分类:

  • sql92标准(只支持内连接)
  • sql99标准

sql92 vs sql99:
功能:99支持的功能更多
可读性:99实现了连接条件和筛选条件的分离,可读性较高
因此,一般较为推荐使用99语法。

6.2.1 sql92标准语法

我们先简单了解一下92语法:

SELECT 查询列表
FROM 表1名, 表2名
WHERE 连接条件;

接着,直接来看例子吧,先来个等值连接的。

沿用表6.1、6.2的数据,我们现在想要查询作者及其作品名,则可以写成:

SELECT a.author_name, b.book_name
FROM authors a,books b
WHERE a.book_id = b.id;

是不是很容易?

再来看一个非等值连接的例子。

依旧假设有两张表,一张是学生成绩表grade,一张是成绩等级表grade_level,具体内容如下:

表6.3: 学生成绩表grade

stu_name grade
小明 98
小刚 86
小强 72
小新 48

表6.4: 成绩等级表grade_level

grade_level lowest_grade highest_grade
A 90 100
B 70 89
C 60 69
D 0 59

现在我们想要查询每个学生的成绩及其等级,这就用到了非等值查询,我们可以写:

SELECT stu_name,grade,grade_level
FROM grade g, grade_level gl
WHERE grade BETWEEN gl.lowest_grade AND gl.highest_grade;

即可得到结果如下:

stu_name grade grade_level
小明 98 A
小刚 86 B
小强 72 B
小新 48 D

最后,来看看自连接

这次只有一张表:员工表employees,表中有三个字段:employee_ id员工编号、name员工姓名、manager_id上级经理编号。现在想要查询的是员工名,以及其上级经理的名字

employee_ id name manager_id
1 小红 NULL
2 小橙 1
3 小黄 1
4 小绿 3
5 小青 2
6 小蓝 4
7 小紫 3

想要查询员工上级的名字,即先找到员工对应上级的编号manager_id(第一次用员工表employees,记作表1)。找到对应上级编号manager_id后,拿着这个编号去比对员工编号employee_ id和name(第二次用员工表employees,记作表2),这就涉及到一表复用,即自连接。

我们可以看到,在第一次用员工表employees时,该表中的employee_ id被看作的是普通员工编号;在第二次用这个表的时候,是将表中的employee_ id当作是担任上级的员工编号。而这两张表之间的连接条件就在于,表1中的上级编号manager_id等于表2中的员工编号employee_ id。

所以,我们可以得到具体过程,如下:

SELECT e.name 员工名, m.name 领导名
FROM employees e, employees m    #此处可以看出起别名的好处,可以清楚地看到我们将前表当成的是普通员工表,后一张表代表的是经理表
WHERE e.manager_id = m.employee_id;

最终结果为:

员工名 领导名
小橙 小红
小黄 小红
小绿 小黄
小青 小橙
小蓝 小绿
小紫 小黄

6.2.2 sql99标准语法

看完了92语法,下面我们瞅瞅99语法下的连接查询,其具体语法如下:

SELECT 查询列表        第⑦步
FROM 表1 别名            第①步
[连接类型] JOIN 表2 别名   第②步
ON 连接条件              第③步
WHERE 筛选条件         第④步
GROUP BY 分组         第⑤步
HAVING 筛选条件        第⑥步
ORDER BY 排序列表      第⑧步

语法中的连接类型主要如下:

1.内连接:inner

  • 等值连接(inner可省略)
  • 非等值连接
  • 自连接

由于上面在92语法中分别举过例子,只是语法上有些许变化,这里就不赘述了。

接下来,一起来看一下92语法并不支持的外连接。

2.外连接:用于查询一个表中有但一个表中没有的记录。 那个有记录的表为主表,没有记录的则为从表。

  • 左外连接:left [outer]
  • 右外连接:right [outer]
  • 全外连接:full [outer] (MySQL不支持)

特点:
1.外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配的值,如果从表中没有和它匹配的,则显示null值。所以,可以列出公式:外连接查询的结果 = 内连接结果+主表中有而从表中没有的结果
2.left左边的是主表,right右边的是主表
3.交换左外连接表的顺序,效果与右外连接一致,右外连接同理
4.全外连接 = 内连接的结果+表1中有但表2没有的结果+表2中有但表1中没有的结果

老规矩,继续上个例子吧。

继续以作家6.1和作品6.2这两张表为例,先将这两张表扩充点记录吧,如下:

表6.1(续): 人物表authors

id author_name sex born_date book_id
1 林徽因 1904-6 2
2 杨绛 1911-7 1
3 毕淑敏 1952-10 3
4 铁凝 1957-9 6
5 严歌苓 1958-11 9
6 迟子建 1964-2 4

表6.2(续): 作品表books

id book_name publishing_date
1 干校六记 1981
2 你是人间四月天 2005
3 蓝色天堂 2011
4 群山之巅 2015

现想要查询作品 不在作品表books中 的作家的名字

我们在做外连接的时候,最关键的一点就在于确定哪张表是主表。在这道题中很容易看出人物表为主表,如果一下子看不出的小伙伴,可以记住一个技巧:找题目的中心词,看最终想要查询的对象是谁。你要查询的信息主要来自于哪个表,谁就是主表。

以这个例题为例,我们最终想要查询的是作家的名字,而作家的名字显然是来自于人物表authors,所以根据我们上面所说的你要查询的信息主要来自于哪个表,谁就是主表可以确定人物表authors为主表。

确定完主表authors,若我们选择左外连接,就将该表放在join左边,若选择的是右外连接,就将其放在右边。

写好连接条件后,即得到authors表中字段作家名 author_name的所有记录,根据之前提及到的外连接特点1可知,作品表books中有和人物表authors匹配的,则显示匹配的值,若无,则返回null。得到结果如下:

author_name id book_name
林徽因 2 你是人间四月天
杨绛 1 干校六记
毕淑敏 3 蓝色天堂
铁凝 NULL NULL
严歌苓 NULL NULL
迟子建 4 群山之巅

通过这个大致的结果表可以更加直观地看到上述的结果。第一列字段来自主表authors,保留着其中的所有条记录;后两列字段均来自从表books,在连接条件下,有匹配的字段显示相应的对应值,没有找到匹配字段的呢,则整条记录显示为null。

有了以上的结果,再来看题目想让我们查询的东西:作品不在作品表里 的作家。换种说法就是在人物表中匹配不到的作家,显而易见,一个is null就可以解决了。

重头梳理一遍,我们可以得到整个查询过程,如下(以左外连接为例,右外连接同理):

SELECT a.author_name
FROM authors a
LEFT [OUTER] JOIN books b     #outer一般可省略
ON a.book_id = b.id
WHERE b.id IS NULL;

3.交叉连接: cross
交叉连接,相当于6.1所说的笛卡尔乘积,这里也不再赘述了。

以上,已解锁全部的连接查询内容啦~

七、子查询

下面我们一起来看看,查询语句中较为复杂点的一类查询:子查询。

含义:出现在其他语句中的select语句,称为子查询或内查询。
这里的其他语句是指,子查询不仅仅可以用在select语句中,增删改中均可以使用。

与子查询(或称为内查询)相对应,外部的查询语句(即包含着子查询的语句)称为主查询(或称为外查询)。

子查询的分类:
1.按结果集的行列数不同:

  • 标量子查询(结果集只有一行一列)
  • 列子查询(结果集只有一列多行)
  • 行子查询(结果集有一行多列或多行多列)
  • 表子查询(结果集一般为多行多列)

2.按照子查询出现的位置:

  • select 后面:仅仅支持标量子查询
  • from 后面:支持表子查询
  • where或having后面:支持标量子查询、列子查询、行子查询(不常用)
  • exists后面(相关子查询):支持表子查询

7.1 where或having后面

由于where或having后面接的子查询更多常见普遍,是子查询中的重点,因此,我们就首先来看看放在该关键字后的子查询。

特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配着单行操作符(<、>、>=、<=、=、<>)使用
列子查询,一般搭配着多行操作符(IN、ANY/SOME、ALL)使用
4.子查询的执行优于主查询的执行,主查询的条件用到了子查询的结果

太抽象?看个例子叭。

【 例1 - 标量子查询 】

以表6.3学生成绩表grade为数据,查询谁的成绩比小强高

表6.3:学生成绩表grade

stu_name grade
小明 98
小刚 86
小强 72
小新 48

首先第一步,我们需要查询出小强的成绩:

SELECT grade
FROM grade
WHERE stu_name = '小强'

很容易得到结果,为:

grade
72

可以看到,得到的结果集一行一列,这就是我们所说的标量子查询。

接着,我们需要查询哪个学生的成绩大于我们上一步所查到的成绩,可以这样写:

SELECT stu_name
FROM grade
WHERE grade > (SELECT grade FROM gradeWHERE stu_name = '小强'
);

这就是一个子查询。

【 例2 - 标量子查询 】

再来看一个用在having后面的子查询的例子。

假设有一张成绩表,包含学生名、班级名、成绩等字段,具体如下:

表7.1: 成绩表grades

stu_name class_id score
小七 2 98
小宝 2 91
小琉 1 86
小璃 3 72
小塔 1 65
小小 3 72
小宗 3 72
小主 1 65

我们现在想要查询,最低分大于一班最低分的班级id和其最低分

第一步,我们应该查出一班的最低分是多少,这肯定是个一行一列的值叭,查询如下:

SELECT MIN(score)
FROM grades
WHERE class_id = 1

第二步,我们是不是应该查询每个班级的最低分,即:

SELECT MIN(score)
FROM grades
GROUP BY class_id

最后,我们基于第二步的结果进行筛选,筛选出最低分大于第一步的结果,查询如下:

SELECT class_id, MIN(score)
FROM grades
GROUP BY class_id
HAVING MIN(score) > (SELECT MIN(score)FROM gradesWHERE class_id = 1
);

【例3 - 列子查询】

在上面特点3中提到,列子查询,一般搭配着多行操作符(IN、ANY/SOME、ALL)使用。所以在看例子前,我们先来简单看一下多行比较操作符的含义是啥。

多行比较操作符 含义
IN / NOT IN 等于列表中的任意一个
ANY / SOME 和子查询返回的某一个值比较
ALL 和子查询返回的所有值比较

懵懵的?来看道题吧。

表7.2: 学生表students

stu_id stu_name class_id score
202001 小三 2 98
202002 小五 5 86
202003 小奥 1 97
202004 小荣 3 72
202005 小竹 1 94
202006 小戴 3 94
202007 小俊 4 81
202008 小娜 2 96
202009 小清 1 98
202010 小昊 3 87
202011 小银 4 66

表7.3: 班级评级表class_level

class_id level
1 A
2 B
3 A
4 C
5 B

查询A类班或B类班所有学生的姓名

第一步,我们先要查到A类班或B类班的班级编号class_id。

SELECT class_id
FROM class_level
WHERE level IN ('A','B')

不难看出,以上查询得到的结果为一列多行,即包含一个字段class_id,多行记录1,2,3,5。这就是上面所说的列子查询。

第二步,基于第一步的结果,查询结果集班级中所有学生的姓名。

SELECT stu_name
FROM students
WHERE class_id IN (SELECT class_idFROM class_levelWHERE level IN ('A','B')
);

这就是一个简单的列子查询。

【例4 - 列子查询】

以表7.2为数据,继续来看道题。

查询其他班级中比三班任一学生成绩低的学生的姓名及成绩

第一步,先查三班所有学生的成绩。

SELECT DISTINCT score
FROM students
WHERE class_id = 3

第二步,再查学生名、成绩,要求成绩小于any(三班所有学生的成绩,即第一步的结果)。

SELECT stu_name, score
FROM students
WHERE score < ANY(SELECT DISTINCT scoreFROM studentsWHERE class_id = 3
) AND class_id <> 3;

最终的查询结果为:

stu_name score
小五 86
小俊 81
小银 66

当然,此处主要是为了练习一下any的用法, 其实我们也可以不用any,只要去查询score小于三班最高分的学生即可。

7.2 select后面

select后面只支持标量子查询,直接来看道题吧。

依旧以表7.2和7.3为源数据,查询各等级的下的学生人数

第一步,查询班级的等级和学生人数。其中班级等级来源于表class_level,学生人数来源于表students,我们可以写出框架,如下:

SELECT cl.*, (SELECT COUNT(*)FROM students
) 学生人数
FROM class_level cl

运行一下,我们可以得到结果:

class_id level 学生人数
1 A 11
2 B 11
3 A 11
4 C 11
5 B 11

显然,学生人数的值是错误的,我们想要得到的是各等级下的学生人数,而现在返回的是总人数。出现错误的原因是,我们的子查询中并没有建立起与主查询的联系。所以,我们接下来要做的是,在子查询里面做一个筛选,让我查询的班级号正好等于等级表中的班级。

SELECT cl.*, (SELECT COUNT(*)FROM students sWHERE s.class_id = cl.class_id
) 学生人数
FROM class_level cl;

再次运行一下,我们可以得到结果:

class_id level 学生人数
1 A 3
2 B 2
3 A 3
4 C 2
5 B 1

嗯?距离我们想要的结果还差一点。

现在得到的学生人数还只是每个班级下的人数,我们想要得到的是各等级下的人数,所有还需要将学生人数按照等级进行汇总。

SELECT level, SUM((SELECT COUNT(*)FROM students sWHERE s.class_id = cl.class_id
)) 学生人数
FROM class_level cl
GROUP BY level;

可得到最终结果:

level 学生人数
A 6
B 3
C 2

7.3 from后面

from后面子查询得到的结果集,实际上就是被当作表来使用,因此必须起别名。具体几行几列都是可以的,主要是看需求。

继续来看个例子。

此处,我们需要用到表7.2和表6.4。

查询每个班级平均分的等级

表7.2: 学生表students

stu_id stu_name class_id score
202001 小三 2 98
202002 小五 5 86
202003 小奥 1 97
202004 小荣 3 72
202005 小竹 1 94
202006 小戴 3 94
202007 小俊 4 81
202008 小娜 2 96
202009 小清 1 98
202010 小昊 3 87
202011 小银 4 66

表6.4: 成绩等级表grade_level

grade_level lowest_grade highest_grade
A 90 100
B 70 89
C 60 69
D 0 59

第一步,查询每个班级的平均分。

SELECT AVG(score),class_id
FROM students
GROUP BY class_id

第二步,将第一步的结果集与成绩等级表grade_level连接,筛选条件为平均分between最低分lowest_grade and 最高分highest_grad,即可得到我们想要的结果,具体查询过程如下:

SELECT avg_score.class_id, gl.grade_level
FROM (SELECT AVG(score) ag, class_idFROM studentsGROUP BY class_id
) avg_score          #必须起别名,否则后面如何表示这个结果集,如何知道是这个“表”
INNER JOIN grade_level gl
ON avg_score.ag BETWEEN gl.lowest_grade AND gl.highest_grade;

7.4 exists后面(相关子查询)

具体的语法:exists(完整的查询语句)
结果:0 或 1
作用:判断查询结果中是否有值,有则返回1,没有则返回0

需要注意一下的是,不同于之前的三种子查询,exists后面的子查询的执行是后于主查询的,是对主查询结果的一个筛选。

来看个例子吧,此处使用表6.1(续)、6.2(续)的数据。

表6.1(续): 人物表authors

id author_name sex born_date book_id
1 林徽因 1904-6 2
2 杨绛 1911-7 1
3 毕淑敏 1952-10 3
4 铁凝 1957-9 6
5 严歌苓 1958-11 9
6 迟子建 1964-2 4

表6.2(续): 作品表books

id book_name publishing_date
1 干校六记 1981
2 你是人间四月天 2005
3 蓝色天堂 2011
4 群山之巅 2015

想要查询有作品的人物名,我们可以这样写:

SELECT author_name
FROM authors a
WHERE EXISTS(SELECT *FROM books bWHERE a.book_id = b.id
);

当然,我们也可以用in来替代exists,如下:

SELECT author_name
FROM authors a
WHERE a.book_id IN (SELECT b.idFROM books b
);

以上,已解锁全部的子查询内容啦~

八、分页查询

当要显示的数据一页显示不全时,就需要分页提交sql请求。

SELECT 查询列表      第⑦步
FROM 表1            第①步
[连接条件] JOIN 表2  第②步
ON 连接条件          第③步
WHERE 筛选条件       第④步
GROUP BY 需要分组的列  第⑤步
HAVING 筛选条件    第⑥步
ORDER BY子句      第⑧步
LIMIT [offset],size   第⑨步
# offset表示的是:要显示条目的索引数(从0开始)
# size表示的是:要显示的条目个数

特点:
1.limit语句放在查询语句的最后
2.要显示N页,已知每页的条目数为size,则可使用公式LIMIT (N-1)*size ,size;

九、联合查询

当我们想要查询的结果来自于多个表,且多个表没有直接的连接关系,但是查询的信息是一致的时候,我们通常会使用联合查询。使用关键字union将多条查询语句的结果合并成一个结果。具体语法如下:

查询语句1
UNION
查询语句2
UNION
...

特点:
1.要求多条查询语句的查询列数是一致的
2.要求多条查询语句查询的每一列的类型和顺序最好一致
3.union关键字默认去重,如果使用union all 可以包含重复项

下面再一起来看个例子,近距离感受一下联合查询的魅力吧。假设现有两个班级的成绩表,如下:

表9.1: 一班的成绩表class1

stu_id stu_name sex grade
1 小明 98
2 小黄 91
3 小刚 86
4 小强 72
5 小知 65
6 小新 48

表9.2: 二班的成绩表class2

id s_name score
01 小红 100
02 小黄 91
03 小蓝 84
04 小绿 71

想要查询一下这两个班成绩在90分以上的学生,给出姓名与成绩

SELECT stu_name, grade FROM class1 WHERE grade > 90
UNION
SELECT s_name, score FROM class2 WHERE score >90;

查询结果如下:

stu_name grade
小明 98
小黄 91
小红 100

细心的小伙伴会注意到,一班和二班的学生名和成绩所使用的字段名是不一样的,在结果中使用的是一班的字段名作为联合表的字段名。所以,可以看见,在使用union进行联合查询时,字段名是默认为第一条语句的字段名的

此外,还有小伙伴可能还会发现,一班和二班都有个叫小黄的学生,并且成绩都超过90分,但是在结果中却只出现了一个小黄的记录。所以,还有一点要记住的是,union是默认去重的当我们需要包含重复项时,可以选择使用union all关键字,语法类似,比如说这里我们应该写成:

SELECT stu_name, grade FROM class1 WHERE grade > 90
UNION ALL
SELECT s_name, score FROM class2 WHERE score >90;

好了,以上便是DQL数据查询语言中最最基础的全部内容啦~

最后,给大家推荐一个SQL在线练习平台:http://sqlfiddle.com/。以上所有内容均可以在这个平台上,自行创建表运行查看。无需注册简单易操作,支持多类SQL语言,是个宝藏网站啦,盖戳~

附该网页图:

MySQL基础(二)查询语句知识点汇总相关推荐

  1. MySQL基础之查询语句

    导入学习数据库 source /opt/yiibaidb.sql SQL是什么?MySQL是什么? SQL是结构化查询语言(Structured Query Language). SQL是一种专门用来 ...

  2. python拷贝是什么知识点_python闭包、深浅拷贝、垃圾回收、with语句知识点汇总...

    1.1 闭包 1.闭包概念 1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包 2. 一般情况下,在我们认知当中,如果一个函数 ...

  3. MySQL 基础 ———— 子查询

    引言 承接<MySQL 基础 ---- 连接查询>,本文介绍和展示SQL中子查询的使用. 子查询是出现在其他语句中的select 语句,也称为内查询.外部的查询语句,称为主查询或外查询. ...

  4. MySQL基础之查询数据

    MySQL基础之查询数据 一.DQL操作表中记录环境搭建 细节:查询只是查看数据,不会修改表中数据 创建商品表(goods2)包含: 商品名称(name),商品价格(price),商品销量(sales ...

  5. mysql+join的原理,Mysql连接join查询原理知识点

    Mysql连接join查询原理知识点 Mysql连接(join)查询 1.基本概念 将两个表的每一行,以"两两横向对接"的方式,所得到的所有行的结果. 假设: 表A有n1行,m1列 ...

  6. MySQL的基本查询语句

    MySQL的基本查询语句 一.数据准备 CREATE TABLE `customers` (`cust_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '顾客I ...

  7. mysql 数据库里查询语句中不等于的两种写法

    mysql 数据库里查询语句中不等于的两种写法 ps:本人亲测,阿里云2核4G5M的服务器性价比很高,新用户一块多一天,老用户三块多一天,最高可以买三年,感兴趣的可以戳一下:阿里云折扣服务器 1.my ...

  8. mysql联表查询语句示例

    mysql联表查询语句示例 ps:本人亲测,阿里云2核4G5M的服务器性价比很高,新用户一块多一天,老用户三块多一天,最高可以买三年,感兴趣的可以戳一下:阿里云折扣服务器 示例: "sele ...

  9. MySQL多表查询语句

    MySQL多表查询语句 1.内连接查询 1.隐式内连接:使用where条件消除无用数据例子: --查询所有员工信息和对应的部门信息SELECT * FROM emp,dept WHERE emp.de ...

最新文章

  1. 2018-3-18 中国计算机之母-- 夏培肃
  2. 旷视提双边分支网络BBN:攻坚长尾分布的现实世界任务 | CVPR 2020 Oral
  3. 微服务架构下的测试之道
  4. Serlvet学习笔记之四—对文件的操作
  5. Asp.Net 2.0中的客户端脚本
  6. JavaScript 获取客户端计算机硬件及系统信息
  7. 电容式传感器位移性能试验报告_一文读懂什么是接近传感器?
  8. 外媒:苹果聘请更多司机在加州测试其自动驾驶汽车
  9. Git学习总结(25)——Git 常用的分支开发模式及规范总结
  10. 简单电子相册视频制作的步骤和要点
  11. paip. mysql如何临时 暂时 禁用 关闭 触发器
  12. Mac OS系统怎么修改mac地址
  13. 百度排名批量查询_企业网站建设,核心关键词排名丢失,怎么办?
  14. python中prompt的意思_Python 基础知识入门
  15. 耶鲁女孩:改变,从背单词开始!(刘畅:我知道耶鲁会录取我的。学习,都要经历死记硬背)
  16. nonebot,cqhttp 机器人学习1
  17. 机动目标跟踪——匀加速运动CA模型(二维)
  18. 百度中的高级搜索功能
  19. qt 侧边栏 Sidebar
  20. docker实践第二版pdf 网盘_和付费网盘说再见,跟着本文自己起个网盘(Java 开源项目)

热门文章

  1. 全网首发微信二维码引擎Android平台移植
  2. 监控系统电子眼安装经验和预防措施
  3. gps校时器(NTP卫星授时服务器)场景应用技术分析
  4. 领导让你做超出本职岗位的工作,欣然接受or 坚决拒绝?
  5. LBP算法(人脸识别特征提取)
  6. electron cookies 应用与封装
  7. Good tool for creating excel : NPOI
  8. C语言求经理三个女儿的年龄,一个经理有三个女儿答案
  9. java中final、finally、finalized使用方法
  10. php调用ip 查询接口,IP地址查询接口及调用方法