• SQL 中的一些小巧但常用的关键字


    前面的几篇文章中,我们大体上介绍了 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% 的记录,但是需要注意的是,只有 SQLserver 数据库实现是支持 TOP 的,各自有各自的关键字作为替代,例如 MySQL 使用 LIMIT 关键字,Oracle 使用 ROWNUM 关键字。

    例如:

    select * from students limit 2;
    

    MySQL 数据库取出前两条数据,等效的 Oracle 数据库写法:

    select * from students
    rownum <= 2
    

    以上的一些关键字虽然逐个看起来很简单,但有时候可能会帮上你大忙的,不要忘记使用它们!。


    关注公众不迷路,一个爱分享的程序员。

    公众号回复「1024」加作者微信一起探讨学习!

    每篇文章用到的所有案例代码素材都会上传我个人 github

    https://github.com/SingleYam/overview_java

    欢迎来踩!

    YangAM 公众号

  • 相关阅读:
    商城项目开发(一)
    java基础
    SpringBoot笔记
    设计模式-创建型模式
    讲真的 曾惜
    Linux常用精简命令实训练习
    使用ZeroClipboard.js复制内容到剪贴板上
    浅谈Jquery中的bind(),live(),delegate(),on()绑定事件方式
    jQuery mouseover与mouseenter,mouseout与mouseleave的区别
    div中的img垂直居中
  • 原文地址:https://www.cnblogs.com/yangming1996/p/10474628.html
Copyright © 2020-2023  润新知