【数据库】SQL语言之数据查询

前言:

现在我们来看看SQL语法的用法,包括查询语句的类型、语法格式和对应的使用场景
这篇我们讲数据查询
数据查询语言是数据库最基本的应用,其语法较为复杂,包括简单查询、带条件查询、连接查询、子查询、集合运算、数据分组、排序和限制等

1. 简单查询

日常查询中 最常用的就是用过FROM子句实现的查询

语法:

SELECT [ , ... ] FROM table_reference [ , ... ] 

使用方法:
SELECT项用于指定要查询的列,FROM指定要从哪个表中查询。
如果要查询所有列,可以在SELECT后面使用*号,如果只查询特定的列,可以直接在SELECT后面指定列名,列名之间用逗号(,)隔开。

例子1:
查询training表中的所有列

SELECT * FROM training;
2. 关键字 DISTINCT

从SELECT的结果集中删除所有重复的行,使结果集中的每行都是唯一的。去重复值查询

例子:
利用distinct关键字来查询员工的岗位和奖金,去除岗位和奖金相同的记录。

select distinct job, bonus from sections;
3. 查询列的选择

例子1:
从多个表中查找多个列

其中,列a、b是表t1中的列,f1、f2是表t2中的列

SELECT a, b, f1, f2 FROM t1, t2;

例子2:
查两个字段计算出来的

SELECT a+b FROM t1;

例子3:
如果某两个或某几个表正好有一些共同的列名,推荐使用表名限定列名。不限定列名可以得到查询结果,但使用完全限定的表和列名称,可以减少数据库内部的处理工作量,从而提升查询的返回性能

SELECT t1.f1, t2.f1 from t1, t2;
4. 别名

通过使用子句AS some_name,可以为表名称或列名称指定另一个标题名显示,一般创建别名是为了让列名称的可读性更强

  • 语法格式:
    列和表的SQL别名分别跟在相应的列名和表名后面,中间可以加或不加一个“AS”关键字。也可以用双引号的方式来表示别名。

    例子:
    表名限定列名,查询学号sid为10的学生的数学成绩和英语成绩

select a.sid,a.score as math, b.score as english from math a,english b where a.sid = 10 and b.sid = 10;
5. 条件查询

在SELECT语句中,可以通过设置条件以达到更精确的查询。条件由表达式与操作符共同指定,且条件返回的值是TRUE,FALSE或UNKNOWN。查询条件可以应用于WHERE子句,HAVING子句。

  1. 比较操作符
    “>, <,>=,<=, !=, <>,=”指定的比较查询条件。当查询条件中和数字比较,可以使用单引号引起,也可以不用,当和字符及日期类型的数据比较,则必须用单引号引起

  2. 逻辑操作符
    常用的逻辑操作符有AND、OR和NOT,他们的运算结果有三个值,分别为TRUE、FALSE和NULL,其中NULL代表未知。他们运算优先级顺序为:NOT>AND>OR

    运算规则表

a b a AND b a OR b NOT a
TRUE TRUE TRUE TRUE FALSE
TRUE FALSE FALSE TRUE FALSE
TRUE NULL NULL TRUE FALSE
FALSE FALSE FALSE FALSE TRUE
FALSE NULL FALSE NULL TRUE
NULL NULL NULL NULL NULL
  1. 测试运算符
    测试运算符指定的范围查询条件
运算符 描述
IN/NOT IN 元素在/不在指定的集合中。
EXISTS/NOT EXISTS 存在/不存在符合条件的元素。
ANY/SOME 存在一个值满足条件。SOME是ANY的同义词。
ALL 全部值满足条件。
BETWEEN…AND… 在两者之间,例如a BETWEEN x AND y等效于a>= x and a <= y。
IS NULL/IS NOT NULL 等于/不等于NULL。
LIKE/NOT LIKE 字符串模式匹配/不匹配。
REGEXP 字符串与正则表达式相匹配,仅支持STRING类型。
REGEXP_LIKE 字符串与正则表达式相匹配,支持STRING类型和NUMBER类型。

例子1:
从表bonuses_depa中查询岗位为developer,且奖金>8000的职员信息

select * from bonuses_depa where job = 'developer' and bonus > 8000;

例子2:
从表bonuses_depa中查询姓wang,且奖金在8500~9500之间的职员信息

select * from bonuses_depa where name like 'wang%' and bonus between 8500 and 9500;

补充:

通配符 %:表示任意数量的字符,包括无字符,用于like和not like语句中。
_:下划线,表示确切的一个未知字符,用于like和not like语句中。

6. join连接查询

实际应用中所需要的数据,经常会需要查询两个或两个以上的表。这种查询两个或两个以上数据表或视图的查询叫做连接查询。连接查询通常建立在存在相互关系的父子表之间。(只要在FROM子句中出现多个表时,数据库就会执行连接)
大多数连接查询包含至少一个连接条件,连接条件可以在FROM子句中也可以在WHERE子句中

举个例子: 对A(4条记录)和B(5条记录)两个表做不指定条件的连接查询时,会得到20(4×5)条记录

语法格式:

SELECT [ , ... ] FROM table_reference
                 [LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER] | INNER]
                 JOIN table_reference
                 [ON { predicate } [ { AND | OR } condition ] [ , ... n ]]

注:table_reference 子句中可以是普通表、视图、子查询

  1. 内连接
    内连接的关键字为inner join,其中inner可以省略。使用内连接,连接执行顺序必然遵循语句中所写的表的顺序。

    例子:
    查询员工ID、最高学历和考试分数。使用training和education两个相关的列(staff_id)做查询操作

SELECT e.staff_id, e.higest_degree, t.score FROM education e JOIN training t ON (e.staff_id = t.staff_id);
  1. 外连接
  • 内连接所指定的两个数据源处于平等的地位。而外连接不同,外连接以一个数据源为基础,将另外一个数据源与之进行条件匹配。
  • 内连接返回两个表中所有满足连接条件的数据记录。外连接不仅返回满足连接条件的记录,还将返回不满足连接条件的记录。
  • 外连接又分为左外连接、右外连接和全外连接。
  1. 左外连接
    又称左连接,如图所示,是指以左边的表为基础表进行查询。
    根据指定连接条件关联右表,获取基础表以及和条件匹配的右表数据,未匹配条件的右表对应的字段位置填上NULL。

    例子:

SELECT e.staff_id, e.higest_degree, t.score FROM education e LEFT JOIN training t ON (e.staff_id = t.staff_id);

在这里插入图片描述

  1. 右外连接
    又称右连接,是指以右边的表为基础表,在内连接的基础上也查询右边表中有记录,而左边的表中没有记录的数据(左边用NULL值填充)。

    例子:

SELECT e.staff_id, e.higest_degree, t.score FROM education e RIGHT JOIN training t ON (e.staff_id = t.staff_id);

在这里插入图片描述

  1. 全外连接
    又称全连接,是指除了返回两个表中满足连接条件的记录,还会返回两个表中不满足连接条件的所有其它行(不匹配的另外一边用NULL值填充)

    例子:

SELECT e.staff_id, e.higest_degree, t.score FROM education e FULL JOIN training t ON (e.staff_id = t.staff_id);

在这里插入图片描述

  1. 半连接
    半连接(Semi Join)是一种特殊的连接类型,在SQL中没有指定的关键字,通过在WHERE后面使用IN或EXISTS子查询实现。当IN/EXISTS右侧的多行满足子查询的条件时,主查询也只返回一行与IN/EXISTS子查询匹配的行,而不是复制左侧的行。

    例子:
    查看参加培训的员工的教育信息。即使training表中的许多行可能与子查询匹配(即同一个staff_id下有多个职员),也只需要从表training返回一行。

SELECT staff_id, higest_degree, education_note FROM education WHERE EXISTS (SELECT * FROM training WHERE education.staff_id = training.staff_id);
  1. 反连接
    反连接(Anti Join)是一种特殊的连接类型,在SQL中没有指定的关键字,通过在WHERE后面使用NOT IN或NOT EXISTS子查询实现。返回所有不满足条件的行。这个关系的概念跟半连接相反。

    例子:

SELECT staff_id, higest_degree, education_note FROM education WHERE staff_id NOT IN (SELECT staff_id FROM training);
7. 子查询

查询是指在查询、建表或插入语句的内部嵌入查询,以获得临时结果集。
子查询可以分为相关子查询非相关子查询

子查询类型 描述
相关子查询 执行查询的时候先取得外层查询的一个属性值,然后执行与此属性值相关的子查询,执行完毕后再取得外层查询的下一个值,依次再来重复执行子查询。
非相关子查询 子查询独立于外层语句(主查询),子查询的执行不需要提前取得父查询的值,只是作为父查询的查询条件。查询执行时子查询和主查询可分为两个独立的步骤,即先执行子查询,再执行主查询。

子查询可以出现在FROM子句、WHERE子句、以及WITH AS子句中。

例子1:
通过相关子查询,查找每个部门中高出部门平均工资的人员

SELECT s1.last_name, s1.section_id, s1.salary
	  FROM staffs s1
	  WHERE salary >(SELECT avg(salary) FROM staffs s2 WHERE s2.section_id = s1.section_id)
	  ORDER BY s1.section_id;

对于staffs表的每一行,父查询使用相关子查询来计算同一部门成员的平均工资。相关子查询为staffs表的每一行执行以下步骤:
确定行的section_id。
然后使用section_id来评估父查询。
如果此行中工资大于所在部门的平均工资,则返回该行。
对于staffs表的每一行,子查询都将被计算一次。

例子2:
WITH子查询:查询培训过big data课程的员工信息

WITH bigdata_staffs AS (select staff_id,exam_date from training where course_name = 'BIG DATA' )select * from bigdata_staffs;

例子3:
通过子查询建立一个和表training具有相同表结构的表

CREATE TABLE training_new AS SELECT * FROM training WHERE  1<>1;

注:<>是不等于的意思,1<>1的条件不成立,所以子查询不会返回数据

例子4:
通过子查询向表training_new表中插入training表的所有数据

INSERT training_new SELECT * FROM training;
8. 合并结果集

除子查询外,还可以使用集合运算符处理多个查询的结果集,输出最终结果

使用语法:

select_statement UNION [ALL] select_subquery

注:Union运算符:将多个查询块的结果集合并为一个结果集输出

使用方法:
• 每个查询块的查询列数目必须相同。
• 每个查询块对应的查询列必须为相同数据类型或同一数据类型组。
•关键字ALL的意思是保持所有重复数据,而没有ALL的情况下表示删除所有重复数据。

理解:
在这里插入图片描述

例子:
现有两个部门的员工信息,查询获得奖金超过7000的员工信息

SELECT staff_id, name, bonus FROM bonuses_depa1 WHERE bonus > 7000 UNION ALL SELECT
staff_id, name, bonus FROM bonuses_depa2 WHERE bonus > 7000 ;

在这里插入图片描述

9. 差异结果集

使用MINUS/ EXCEPT运算符。对查询结果集的减法,计算存在于左边查询语句的输出、而不存在于右边查询语句输出的结果

比如:A minus B C就意味着将结果集A去除结果集B和结果集C中所包含的所有记录后的结果,即在A中存在,而在B、 C中不存在的记录

语法格式:

select_statement MINUS/EXCEPT select_statement2 [ ... ]

理解:
在这里插入图片描述

10. 数据分组
  1. GROUP BY
    数据库查询中,分组是一个非常重要的应用。分组是指将数据表中的记录以某个或者某些列为标准,值相等的划分为一组。

    语法格式

GROUP BY { column_name } [ , ... ]

使用方法:
○ GROUP BY子句中的表达式可以包含FROM子句中表,视图的任何列,无论这些列是否出现在SELECT列表中。
○ GROUP BY子句对行进行分组,但不保证结果集的顺序。 要对分组进行排序,请使用ORDER BY子句。
○ GROUPBY后的表达式可以使用括号,如: group by (expr1, expr2),或者 group by(expr1), (expr2)。但不支持 group by (expr1, expr2), expr3 格式。

例子:
该部门按照岗位和奖金分组,查询每组员工数,结果按人数升序排序

select job, bonus, count(staff_id) sum from bonuses_depa group by(job,bonus) order by sum;

在这里插入图片描述
2. HAVING子句
与GROUP BY子句配合用来选择特殊的组。HAVING子句将组的一些属性与一个常数值比较,只有满足HAVING子句中条件的组才会被提取出来

语法格式:
HAVING condition [ , ... ]

例子:
查询表sections中岗位人数大于3的各岗位员工总数。

select job, count(staff_id) from bonuses_depa group by job having count(staff_id) >3;
11. 数据排序
  1. ORDER BY子句

    使用ORDER BY子句对查询语句返回的行根据指定的列进行排序。如果没有ORDER BY子句,则多次执行的同一查询将不一定以相同的顺序进行行的检索。

    语法格式:

ORDER BY { column_name | number | expression } [ ASC | DESC ][ NULLS FIRST | NULLS LAST ] [ , ... ]

使用方式:
○ column_name | number | expression 表示 order by 后面可以跟列名、数字、表达式(跟数字:order by 1 表示 根据查询选择列中第一个字段排序。跟表达式:order by(column1+column2) 表示根据column1与column2的和的大小来排序。)
○ ORDER BY语句默认按照升序对记录进行排序。如果希望按照降序对记录进行排序,请使用DESC关键字。
○ NULLS FIRST | NULLS LAST 关键字指定ORDER BY列中NULL值的排序位置,FIRST表示将NULL值排在最前面,LAST表示将NULL值排在最后面,若不指定该选项, ASC默认为NULLS LAST, DESC默认为NULLS FIRST。

例子:
查询下表bonuses_depa中各工种的奖金信息,查询结果先按bonus升序排列,然后按name降序排列

select * from bonuses_depa order by bonus,name desc;

在这里插入图片描述

12. 数据限制

数据限制功能包括两个独立的子句,LIMIT子句和OFFSET子句

  • LIMIT子句允许限制查询返回的行。 可以指定偏移量,以及要返回的行数或行百分比。 可以使用此子句实现top-N报表。要获得一致的结果,请指定ORDER BY子句以确保确定性排序顺序
LIMIT { count | ALL }
  • OFFSET子句设置开始返回的位置
OFFSET start

使用方法
○ start:指定在返回行之前要跳过的行数。
○ count:指定要返回的最大行数。
○ start和count都被指定时,在开始计算要返回的count行之前会跳过start行
○ LIMIT 5,20与LIMIT 20 OFFSET 5及OFFSET 5 LIMIT 20 均表示跳过5行后输出20行记录

例子:
查询下表 bonuses_depa中的员工信息。通过增加LIMIT 2 OFFSET 1限定查询时跳过前1行后,查询总共2行数据

SELECT name, job, bonus FROM bonuses_depa LIMIT 2 OFFSET 1;

在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章