数据查询介绍
数据查询是数据库的核心操作。SQL提供了SELECT
语句进行数据查询,该语句具有灵活的使用方式和丰富的功能。其一般格式为:
/*"[]"表可选,"<>"表必选*/
SELECT [ALL|DISTINCT] <目标列表达式> [,<目标列表达式>] ...
FROM <表名或视图名> [,<表名或视图名>...] | (<SELECT语句>) [AS] <别名>
[WHERE <条件表达式>]
[GROUP BY <列名1> [HAVING <条件表达式>]]
[ORDER BY <列名2> [ASC|DESC]];
上面语句的含义为:
- 根据
WHERE
子句的条件表达式从FROM
子句指定的基本表、视图或派生表中找出满足条件的元组,再按SELECT
子句中的目标列表达式选出元组中的属性值形成结果表。 - 如果有
GROUP BY
子句,则将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。如果GROUP BY
子句带HAVING
短语,则只有满足指定条件的组才予以输出。 - 如果有
ORDER BY
子句,则结果还要按<列名2>的值升序(ASC)或降序(DESC)排序。
SELECT语句既可以完成简单的单表查询,也可以完成复杂的连接查询和嵌套查询。
单表查询
单表查询指仅涉及一个表的查询。下面以上一篇文章中建立的用户表为例进行查询。
一、选择其中若干列
1. 查询指定列
很多时候用户只对表中的一部分列中的数据有需要,这时可以通过<目标列表达式>指定要查询的属性列。
/* 查询全部用户的性别与生日 */
SELECT gender, birthday
FROM t_user;
2. 查询全部列
查询全部列有两种方法,一种方法是直接列出所有列名,也可以直接使用 “*” 代替(区别在于是否需要以原本的顺序显示结果)。
/* 查询全部用户的全部信息 */
SELECT *
FROM t_user;
3. 查询经过计算的值
<目标列表达式>不仅可以是表中的属性列,也可以是算数表达式、字符串常量、函数等。
/* 查询用户的姓名和根据生日计算出的年龄 */
SELECT username, TIMESTAMPDIFF(YEAR, birthday, CURDATE())
FROM t_user;
/* 还可以给函数表达式定义别名,便于查看结果 */
SELECT username, TIMESTAMPDIFF(YEAR, birthday, CURDATE()) age
FROM t_user;
TIMESTAMPDIFF函数为计算时间差,CURDATE函数为获取当前日期。
二、选择表中的若干元组
1. 消除取值重复的行
两个并不完全相同的元组在投影到某些指定的列时,可能会变成相同的行。可以使用DISTINCT
消除它们。如果没有指定DISTINCT
关键词,则默认为ALL
,即保留结果表中重复的行。
sql SELECT DISTINCT birthday FROM t_user;
2. 查询满足条件的元组
查询满足指定条件的元组可以通过WHERE
子句实现。WHERE
子句常用的查询条件如下表所示:
查询条件 | 谓词 |
---|---|
比较大小 | =, >, <, >=, !=, <>, !>, !<; NOT+上述比较符 |
确定范围 | BETWEEN AND, NOT BETWEEN AND |
确定集合 | IN, NOT IN |
字符匹配 | LIKE, NOT LIKE |
空值 | IS NULL, IS NOT NULL |
多重条件(逻辑运算) | AND, OR, NOT |
-
比较大小:用于比较的运算符包括=(等于), >(大于), <(小于), >=(大于等于), !=或<>(不等于), !>(不大于), !<(不小于)。例:
/* 查询大于等于2020/11/11的生日 */ SELECT DISTINCT birthday FROM t_user WHERE birthday >= '2020/11/11';
-
确定范围:谓词
BETWEEN···AND···
和NOT BETWEEN···AND···
可以用来查找属性值在(或不在)范围内的元组,其中AND
前是下限,AND
后是上限。例:/* 查询id在10002-10005之间的用户信息 */ SELECT * FROM t_user WHERE userid BETWEEN 10002 AND 10005;
-
确定集合:谓词
IN
可以用来查找属性值属于指定集合的元组,NOT IN
与之相反。例:/* 查找生日不是2020.11.11和2020.12.02的用户信息 */ SELECT * FROM t_user WHERE birthday NOT IN('2020.11.11', '2020.12.02');
-
字符匹配:谓词
LIKE
可以用来进行字符串的匹配,其一般格式如下,含义是查找指定的属性列值与<匹配串>相匹配的元组。[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>']
-
<匹配串>可以是一个完整的字符串,也可以含有通配符“%”和“_”。
-
“%”代表任意长度(长度可以为0)的字符串,如
a%b
表示任意以a开头以b结尾的任意长度的字符串。例:/* 查找密码以a结尾的用户信息 */ SELECT * FROM t_user WHERE pwd LIKE '%a';
-
“_”代表任意单个字符,如
a_b
表示任意以a开头以b结尾的长度为3的字符串。例:/* 查找用户名以“亚”结尾长度为2的用户信息 */ SELECT * FROM t_user WHERE username LIKE '_亚';
-
如果
LIKE
后的匹配串不含任意通配符,则与’='等价。 -
ESCAPE'\'
表示“\”为换码字符。这样匹配串中跟在“\”后的字符“_”不再具有通配符的含义,转义为普通的“_”字符。
-
三、ORDER BY子句
用户可以使用ORDER BY
子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认值为升序。例:
/* 按生日降序排列用户信息 */
SELECT *
FROM t_user
ORDER BY birthday DESC;
对于空值,排序时显示的次序由具体系统实现来决定。
四、聚集函数
为进一步方便用户,增强检索功能,SQL提供了许多聚集函数,主要有:
COUNT(*) /* 统计元组个数 */
COUNT([DISTINCT|ALL] <列名>) /* 统计一列中值的个数 */
SUM([DISTINCT|ALL] <列名>) /* 计算一列值的总和(必须是数值型)*/
AVG([DISTINCT|ALL] <列名>) /* 计算一列值的平均值(必须是数值型)*/
MAX([DISTINCT|ALL] <列名>) /* 计算一列值的最大值 */
MIN([DISTINCT|ALL] <列名>) /* 计算一列值的最小值 */
- 如果指定
DISTINCT
短语,则表示在计算中要取消指定列中的重复值。如果不指定DISTINCT
短语或指定ALL
短语(ALL为默认值),则表示不取消重复值。 - 当聚集函数遇到空值时,除
COUNT(*)
外,都跳过空值而只处理非空值。COUNT(*)
是对元组进行计数,某个元组部分列为空不影响计数。/* 查询性别为女的用户数量 */ SELECT COUNT(*) FROM t_user WHERE gender = '女';
注意:
WHERE
子句中不能使用聚集函数做条件表达式。聚集函数只能用于SELECT
和GROUP BY
中的HAVING
子句。
五、GROUP BY子句
-
GROUP BY
子句将查询结果按某一列或多列的值分组,值相等的分为一组。 -
对查询结果分组可以细化聚集函数的作用对象,分组后聚集函数将作用于每个组,即每一组都有一个函数值。
-
如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则可以使用
HAVING
短语指定筛选条件。 -
WHERE
子句与HAVING
短语的区别在于作用对象不同。WHERE
子句作用于基本表或视图,从中选择满足条件的元组。HAVING
短语作用于组,从中选择满足条件的组。因此,WHERE
子句中不能使用聚集函数做条件表达式。/* 按生日分组,且要求每组人数不得大于2 */ SELECT birthday, COUNT(*) num FROM t_user GROUP BY birthday HAVING COUNT(*) <= 2;