前面的几篇文章中, 我们大体上介绍了 SQL 中基本的创建, 查询语句, 甚至也学习了相对复杂的连接查询和子查询, 这些基本功相信你也一定掌握的不错, 那么本篇则着重介绍几个技巧方面的关键字, 能够让你更快更有效率的写出一些 SQL.
起别名
在实际的项目中, 有时候我们的表名, 字段名过于复杂以致于我们的 SQL 写出来过长, 过于复杂, 这时候我们往往会通过起别名的方式将一些名字较长, 较为复杂的字段或是表名简化.
我们可以使用别名 (Alias) 来对数据表或者列进行临时命名, 既然是别名, 也就是说并不会修改原表或列的原始名称, 仅仅用于当前查询的简介化显示.
给表起别名:
- select * from person as p
- where p.id = 1;
一旦为表执行了别名, 那么本次查询的子查询语句中都可以直接引用别名替代原表的引用.
给列起别名:
select name as n,age as a from perosn;
除了使用关键字 as 来给表或是列起别名外, 还可以直接使用空格字符达到同样的效果, 但是个人认为要么全部使用 as 进行别名, 要么全部使用空格进行别名, 不要交叉使用使得你的 SQL 复杂又难以看懂.
消除重复记录
有时候, 我们的数据库中会存在两条完全一样的数据, 我们也叫做冗余数据, 当然不希望在查询数据的时候查出来这么些冗余的重复数据, 我们要把它们过滤掉.
LeetCode 上的一道简单题:
有一个 courses 表 , 有: student (学生) 和 class (课程).
请列出所有超过或等于 5 名学生的课.
例如, 表:
- +---------+------------+
- | student | class |
- +---------+------------+
- | A | Math |
- | B | English |
- | C | Math |
- | D | Biology |
- | E | Math |
- | F | Computer |
- | G | Math |
- | H | Math |
- | I | Math |
- +---------+------------+
应该输出:
- +---------+
- | class |
- +---------+
- | Math |
- +---------+
你可以花个一分钟思考一下, 运用我们之前的基本功, 应该是不难的.
显然是需要用到分组的, 想要统计每门课有多少人选, 就得按照学科进行分组, 每个分组内就是该门学科选修的学生记录.
那么 SQL 语句也就信手拈来了:
- select class from courses
- group by class
- having count(student)>=5
但是你提交后在海量测试用例下, 会返回给你解答错误的提示, 不信你试试, 问题出在哪?
问题就出现在冗余数据这个边界条件没有被考虑, 如果 A 选了两次 Math, 当我们对 Math 这个分组进行计数时就会多算一次选 Math 的人数, 实际上这是不符合逻辑的, 我们需要过滤掉那些重复选择的数据记录.
解决方案如下:
- select class from courses
- group by class
- having count(distinct student)>=5
有些人可能看出来了, 我们在 count 函数的列参数前添加了一个 distinct 关键字, 它表示如果 student 列的值重复出现的话只计数一次.
当然, distinct 除了可以在聚合函数中使用外, 也可以直接用在查询语句的列筛选阶段, 例如:
- // 取出所有的学生, 不允许重复名字的学生同时出现
- select distinct name from students
连接结果集
UNION 运算符可以将一个或多个 SELECT 语句的结果连接组合成一个结果集, 但要求两个或多个结果具有相同数量的列, 列的数据类型相同, 举个例子:
构建一个学生表:
- +----+------+----------+-------+
- | id | name | uNo | fees |
- +----+------+----------+-------+
| 1 | 张三 | 15263501 | 18000 |
| 2 | 李四 | 15263506 | 15960 |
| 3 | 王二 | 15263512 | 2500 |
+----+------+----------+-------+
学生表主要有学生的姓名, 学号和学费.
构建一个教师表:
- +----+--------+------+--------+
- | id | name | tNo | salary |
- +----+--------+------+--------+
| 1 | 李老师 | 1001 | 10000 |
| 2 | 杨老师 | 1002 | 15000 |
| 3 | 曹老师 | 1030 | 5000 |
+----+--------+------+--------+
现在有一个需求, 需要拿到全校所有人的姓名和编号, 包括学生和老师. 一般来说, 我们两次 select 查询就好了, 但是没法合并在一个结果集中显示, 这是一个问题.
于是我们可以使用 union 来连接两个结果并在一张表中显示出来:
- select name,uNo from students
- union
- select name,tNo from teacher
查询结果:
- +--------+----------+
- | name | uNo |
- +--------+----------+
| 张三 | 15263501 |
| 李四 | 15263506 |
| 王二 | 15263512 |
| 李老师 | 1001 |
| 杨老师 | 1002 |
| 曹老师 | 1030 |
+--------+----------+
看起来是不是直观了很多, 除此之外的是, 如果两个结果集中存在完全重复的数据记录, 合并后的结果集中不会重复出现该数据记录.
当然了, 如果你不需要在合并结果集的时候删除掉重复的数据行, 你可以转而使用关键字 UNION ALL 替代 UNION.
TOP
TOP 子句用于从一张数据表中取回前 N 个或者 X% 的记录, 但是需要注意的是, 没有一个数据库实现是支持 TOP 的, 各自有各自的关键字作为替代, 例如 MySQL 和 SQLserver 使用 LIMIT 关键字, Oracle 使用 ROWNUM 关键字.
例如:
select * from students limit 2;
MySQL 数据库取出前两条数据, 等效的 Oracle 数据库写法:
- select * from students
- rownum <= 2
以上的一些关键字虽然逐个看起来很简单, 但有时候可能会帮上你大忙的, 不要忘记使用它们!.
关注公众不迷路, 一个爱分享的程序员.
公众号回复「1024」加作者微信一起探讨学习!
每篇文章用到的所有案例代码素材都会上传我个人 GitHub
https://github.com/SingleYam/overview_java
欢迎来踩!
来源: https://www.cnblogs.com/yangming1996/p/10474628.html