6、职能岗SQL学习极简攻略-合并查询
合并查询
在前文我们介绍了如何使用子查询和连接查询在多个表中查询数据,本节我们将介绍另一种在多表中查询数据的方法:合并查询。
合并查询顾名思义就是将多个查询结果合并在一起,比如我们现在有如下两张表:学生表和老师表,我们想要查询学校中的所有人员信息(包括老师和学生),这时候我们就可以使用合并查询。
学生表(表名为students):
id | name | telephone | gender | class |
---|---|---|---|---|
1 | 屈屈 | 18820030216 | 女 | 1班 |
2 | 慧心 | 13268751479 | 男 | 2班 |
3 | 达琳 | 15754874518 | 女 | 1班 |
4 | 森贝 | 13698742277 | 女 | 2班 |
5 | 米粒 | 13698652689 | 男 | 1班 |
老师表(表名为teachers):
id | name | telephone | gender |
---|---|---|---|
1 | 困困 | 13026324789 | 女 |
2 | 毛毛 | 13658748974 | 男 |
3 | 米粒 | 13265877158 | 男 |
UNION
我们想要查询学校中所有人员的姓名和电话号码,此时可以使用如下SQL语句:
1 | SELECT name, telephone FROM students |
这里的UNION
就表示取两个查询结果的并集,即将两个查询结果合并在一起。
其中SELECT name, telephone FROM students
为第一个查询,SELECT name, telephone FROM teachers
为第二个查询,将两个查询结果合并在一起,我们就得到了学校中所有人员的姓名和电话号码:
name | telephone |
---|---|
屈屈 | 18820030216 |
慧心 | 13268751479 |
达琳 | 15754874518 |
森贝 | 13698742277 |
米粒 | 13698652689 |
困困 | 13026324789 |
毛毛 | 13658748974 |
米粒 | 13265877158 |
也就是说UNION
会将两个查询结果合并在一起,那如果两个查询的列不一样会怎么样呢?我们来看一个例子:
1 | SELECT name, telephone FROM students |
第一个查询的列是name
和telephone
,而第二个查询的列是telephone
和name
,这两个查询的列不一样,那么UNION
会如何处理呢?
将会返回如下结果,可以看到UNION
会将两个查询结果合并在一起,不管两个查询的列是否一样,使用第一个查询的列作为最终结果的列。这样的查询实际并没有意义,在使用时应注意避免。
name | telephone |
---|---|
屈屈 | 18820030216 |
慧心 | 13268751479 |
达琳 | 15754874518 |
森贝 | 13698742277 |
米粒 | 13698652689 |
13026324789 | 困困 |
13658748974 | 毛毛 |
13265877158 | 米粒 |
UNION ALL
UNION
会去除重复的行,如果我们想要保留重复的行,则可以使用UNION ALL
。例如学生表和老师表中都有一名叫”米粒“的人,我们想要查询学校中所有人员的姓名,此时可以使用如下SQL语句:
1 | SELECT name FROM students |
可以看到UNION ALL
会保留重复的行,最终结果含有两个名字为”米粒“的行:
name |
---|
屈屈 |
慧心 |
达琳 |
森贝 |
米粒 |
困困 |
毛毛 |
米粒 |
我们再和只使用UNION
的结果对比下:
1 | SELECT name FROM students |
其返回的结果为:
name |
---|
屈屈 |
慧心 |
达琳 |
森贝 |
米粒 |
困困 |
毛毛 |
可以看到UNION
去除了重复的行,只保留了一个名字为”米粒“的行。
其中UNION
也可以写作UNION DISTINCT
,更明显的表示去除重复的行,两者是等价的:
1 | SELECT name FROM students |
排序
我们可以对合并后的结果进行排序,例如我们想要按照id降序排列,可以使用如下SQL语句:
1 | SELECT id, name, telephone FROM students |
可以看到id按照降序排列:
id | name | telephone |
---|---|---|
5 | 米粒 | 13698652689 |
4 | 森贝 | 13698742277 |
3 | 达琳 | 15754874518 |
3 | 米粒 | 13265877158 |
2 | 慧心 | 13268751479 |
2 | 毛毛 | 13658748974 |
1 | 屈屈 | 18820030216 |
1 | 困困 | 13026324789 |
从上述结果中可以看到ORDER的生效范围是合并后的全部数据,那么是否可能对两个查询结果分别排序呢?我们来看一个例子:
1 | (SELECT id, name, telephone FROM students ORDER BY id DESC) |
这里使用括号来将两个查询扩起来,尝试分别对两个查询结果进行排序,我们来看下返回结果:
id | name | telephone |
---|---|---|
1 | 屈屈 | 18820030216 |
2 | 慧心 | 13268751479 |
3 | 达琳 | 15754874518 |
4 | 森贝 | 13698742277 |
5 | 米粒 | 13698652689 |
1 | 困困 | 13026324789 |
2 | 毛毛 | 13658748974 |
3 | 米粒 | 13265877158 |
可以看到实际并没有产生效果,并没有如预期id为5,4,3,2,1等等。也就是说对合并前的结果排序是没有效果的!
筛选
我们可以在合并后的结果上进行筛选,例如我们想要查询姓名为”屈屈“的人员信息,但是并不知道她是学生还是老师,则可以使用如下SQL语句:
1 | SELECT * FROM |
这里使用括号将两个查询扩起来,然后在外层查询中对合并后的结果进行筛选,其中temp为合并后的结果的别名,这样我们就可以在外层查询中对合并的结果进行筛选,就好像操作一张名为temp的表一样。将返回如下结果:
id | name | telephone |
---|---|---|
1 | 屈屈 | 18820030216 |
细心的你可能会疑惑,在排序小节我们可以对合并后的结果直接排序,那么是否可以类似的对合并后的结果进行筛选呢?我们来看一个例子:
1 | SELECT id, name, telephone FROM students |
我们仿照排序的写法,尝试在合并后的结果上进行筛选,我们来看下返回结果:
id | name | telephone |
---|---|---|
1 | 屈屈 | 18820030216 |
2 | 慧心 | 13268751479 |
3 | 达琳 | 15754874518 |
4 | 森贝 | 13698742277 |
5 | 米粒 | 13698652689 |
可以发现,其查询结果并不正确,所以在合并后的结果上进行筛选时,应当在外层查询中对合并后的结果进行筛选。
当然了,你也可以通过在每个查询中进行筛选,然后再合并,例如我们想要查询姓名为”屈屈“的学生和老师信息,可以使用如下SQL语句:
1 | (SELECT id, name, telephone FROM students WHERE name = '屈屈') |
将返回如下结果:
id | name | telephone |
---|---|---|
1 | 屈屈 | 18820030216 |