数据库最大的功能也是最常用的就是slct方法,也就是我们常说的数据查询,在不同的数据库的面试中是必考的内容,因此掌握slct查询方法是多么的重要。
基于《三国志》的游戏数据,学习slct语句检索表记录的方法、wh语句过滤数据集的方法、数据结果集合排序、聚合查询数据、合并查询、子查询等内容。
slct语句概述
slct语句的语法
slct字段列表from数据源[wh条件表达式][groupby分组字段[having条件表达式][ordrby排序字段[asc
dsc]]
使用slct子句指定字段列表
可以为字段列表中的字段名或表达式指定别名,中间使用as关键字分隔即可(as关键字可以省略)。
SELECTsan_wujiang.`姓名`,san_wujiang.`姓名`AS武将姓名FROMsan_wujiang;
使用谓词限制记录的行数
MySQL中的两个谓词distinct和limit可以限制记录的行数。
distinct过滤结果集中的重复记录
数据库表中不允许出现重复的记录,但这不意味着slct的查询结果集中不会出现记录重复的现象。如果需要过滤结果集中重复的记录,可以使用谓词关键字distinct。
SELECTDISTINCT`官职`FROMsan_wujiang;
limit查询某几行记录
查询前几条或者中间某几条记录,可以使用谓词关键字limit实现。
//查询前10条记录SELECT`姓名`FROMsan_wujiangLIMIT10;
//查询10到20条记录SELECT`姓名`FROMsan_wujiangLIMIT10,20;
使用from子句指定数据源
多张数据库表(或者视图)缝补成一个结果集时,需要指定缝补条件,该缝补条件称为连接条件。
from表名1[连接类型]join表名2on表1和表2之间的连接条件
SQL标准中的连接类型主要分为innr连接(内连接)和outr连接(外连接),而外连接又分为lft(左外连接,简称为左连接)、right(右外连接,简称为右连接)以及full(完全外连接,简称完全连接)。
内连接(innrjoin)
内连接将两个表中满足指定连接条件的记录连接成新的结果集,舍弃所有不满足连接条件的记录。内连接是最常用的连接类型,也是默认的连接类型,可以在from子句中使用innrjoin(innr关键字可以省略)实现内连接,语法格式如下。
SELECTsan_wujiang.`势力`,san_shili.`君主`,san_wujiang.`姓名`FROMsan_shiliINNERJOINsan_wujiangONsan_wujiang.`势力`=san_shili.`君主`
外连接(outrjoin)
外连接又分为左连接(lftjoin)、右连接(rightjoin)和完全连接(full)。与内连接不同,外连接(左连接或右连接)的连接条件只过滤一个表,对另一个表不进行过滤(该表的所有记录出现在结果集中)。MySQL暂不支持完全连接。
左连接,语法格式中表1左连接表2,意味着查询结果集中须包含表1的全部记录,然后表1按指定的连接条件与表2进行连接,若表2中没有满足连接条件的记录,则结果集中表2相应的字段填入NULL。
SELECTsan_wujiang.`势力`,san_shili.`君主`,san_wujiang.`姓名`FROMsan_shiliLftJOINsan_wujiangONsan_wujiang.`势力`=san_shili.`君主`
右连接,语法格式中表1右连接表2,意味着查询结果集中须包含表2的全部记录,然后表2按指定的连接条件与表1进行连接,若表1中没有满足连接条件的记录,则结果集中表1相应的字段填入NULL。
SELECTsan_wujiang.`势力`,san_shili.`君主`,san_wujiang.`姓名`FROMsan_shiliRightJOINsan_wujiangONsan_wujiang.`势力`=san_shili.`君主`
多表连接
From表1[连接类型]join表2on表1和表2之间的连接条件[连接类型]join表3on表2和表3之间的连接条件SELECTsan_shili.`君主`,san_wujiang.`姓名`,san_city.`势力`FROMsan_shiliINNERJOINsan_wujiangONsan_wujiang.`势力`=san_shili.`君主`INNERJOINsan_cityONsan_shili.`君主`=san_city.`势力`
使用wh子句过滤结果集
wh条件表达式
数据库中存储着海量数据,数据库用户往往需要的是满足特定条件的记录,wh子句可以实现结果集的过滤筛选。
使用单一的条件过滤结果集
单一的过滤条件可以使用下面的布尔表达式表示。
表达式1比较运算符表达式2
表达式1和表达式2可以是一个字段名、常量、变量、函数甚至是子查询。
比较运算符用于比较两个表达式的值,比较的结果是一个布尔值(tru或者fals)。
常用的比较运算符有=(等于)、(大于)、=(大于等于)、(小于)、=(小于等于)、(不等于)、!=(不等于)、!(不小于)、!(不大于)。
如果表达式的结果是数值,则按照数值的大小进行比较;如果表达式的结果是字符串,则需要参考字符序collation的设置进行比较。
//选择刘备下属武将SELECTsan_wujiang.`姓名`FROMsan_wujiangWHEREsan_wujiang.`势力`=刘备
isNULL运算符
isNULL用于判断表达式的值是否为空值NULL(isnot恰恰相反),
表达式is[not]NULL
不能将字段isNULL写成某字段=NULL,原因是NULL是一个不确定的数,不能使用=、!=等比较运算符与NULL进行比较。
//选择在野武将SELECTsan_wujiang.`姓名`FROMsan_wujiangWHEREsan_wujiang.`势力`=Null
使用逻辑运算符
wh子句中可以包含多个查询条件,使用逻辑运算符可以将多个查询条件组合起来,完成更为复杂的过滤筛选。常用的逻辑运算符包括逻辑与(and)、逻辑或(or)以及逻辑非(!),其中逻辑非(!)为单目运算符。
逻辑非(!)
为单目运算符,逻辑非(!)的使用方法较为简单,如下所示。使用逻辑非(!)操作布尔表达式时,布尔表达式的值为tru时,整个逻辑表达式的结果为fals,反之亦然。
//选择非刘备下属武将SELECTsan_wujiang.`姓名`FROMsan_wujiangWHEREsan_wujiang.`势力`!=刘备
and逻辑运算符
使用and逻辑运算符连接两个布尔表达式时,只有两个布尔表达式的值都为tru时,整个逻辑表达式的结果才为tru。
//定义势力和官职条件SELECTsan_wujiang.`姓名`FROMsan_wujiangWHEREsan_wujiang.`势力`=刘备ANDsan_wujiang.`官职`=破贼校尉
另外MySQL还支持btwn…and…运算符,btwn…and…运算符用于判断一个表达式的值是否位于指定的取值范围内,btwn…and…的语法格式如下。
//选择刘备势力忠诚-的武将SELECTsan_wujiang.`姓名`FROMsan_wujiangWHEREsan_wujiang.`势力`=刘备andsan_wujiang.`忠诚`btwnand
or逻辑运算符
连接两个布尔表达式时,只有两个表达式的值都为fals时,整个逻辑表达式的结果才为fals。语法格式如下。
//选择武将身份是破贼校尉或者典农校尉SELECTsan_wujiang.`姓名`,san_wujiang.`官职`FROMsan_wujiangWHEREsan_wujiang.`官职`=破贼校尉ORsan_wujiang.`官职`=典农校尉
in运算符in运算符用于判定一个表达式的值是否位于一个离散的数学集合内,in的语法格式如下。
//选择身份在(破贼校尉,典农校尉,长水校尉)中的武将SELECTsan_wujiang.`姓名`,san_wujiang.`官职`FROMsan_wujiangWHEREsan_wujiang.`官职`in(破贼校尉,典农校尉,长水校尉)
lik模糊查询
用于判断一个字符串是否与给定的模式相匹配。
模式是一种特殊的字符串,特殊之处在于不仅包含普通字符,还包含有通配符。在实际应用中,如果不能对字符串进行精确查询,此时可以使用lik运算符与通配符实现模糊查询。
模糊查询%或者_字符时,需要字符转义。
字符串表达式[not]lik模式
例如武将姓名中所有带“曹”的人员信息。
SELECTsan_wujiang.`姓名`,san_wujiang.`官职`FROMsan_wujiangWHEREsan_wujiang.姓名LIKE%曹%
ordrby对结果集排序
ordrby子句用于对结果集排序。在slct语句中添加ordrby子句,就可以使结果集中的记录按照一个或多个字段的值进行排序,排序的方向可以是升序(asc)或降序(dsc)。
ordrby字段名1[asc
dsc][…,字段名n[asc
dsc]]//按照出生年正序排序SELECTsan_wujiang.`姓名`,san_wujiang.`出生年`FROMsan_wujiangORDERBYsan_wujiang.`出生年`asc
//按照出生年倒序排序SELECTsan_wujiang.`姓名`,san_wujiang.`出生年`FROMsan_wujiangORDERBYsan_wujiang.`出生年`dsc
运算聚合函数汇总结果
聚合函数用于对一组值进行计算并返回一个汇总值,常用的聚合函数有累加求和sum()函数、平均值avg()函数、统计记录的行数count()函数、最大值max()函数和最小值min()函数等。
使用count()对NULL值统计时,count()函数将忽略NULL值。sum()函数、avg()函数、max()以及min()函数等统计函数,统计数据时也将忽略NULL值。
groupby子句分组统计
groupby子句将查询结果按照某个字段(或多个字段)进行分组(字段值相同的记录作为一个分组。groupby子句通常与聚合函数一起使用。
groupby字段列表[having条件表达式][withrollup]
groupby子句与聚合函数
例如统计每一个国家势力的武将人数。例如统计每个武将的平均年龄,武力、智力、政治、魅力等数据信息。
groupby子句与having子句
having子句用于设置分组或聚合函数的过滤筛选条件,having子句通常与groupby子句一起使用。having子句语法格式与wh子句语法格式类似。
having条件表达式
其中条件表达式是一个逻辑表达式,用于指定分组后的筛选条件。
slct语句的语法格式中,slct语句的执行过程为:首先使用wh子句对结果集进行过滤筛选,接着groupby子句分组wh子句的输出,最后having子句从分组的结果中再进行筛选。
slct字段列表from数据源Wh条件表达式groupby分组字段having条件表达式
groupby子句与group_concat()函数
group_concat()函数的功能是将集合中的字符串连接起来,此时group_concat()函数的功能与字符串连接函数concat()的功能相似。
group_concat()函数的功能是将集合中的字符串连接起来,此时group_concat()函数的功能与字符串连接函数concat()的功能相似。
slctgroup_concat(刘备,关羽,张飞);concat(刘备,关羽,张飞);
group_concat()函数还可以按照分组字段,将另一个字段的值(NULL值除外)使用逗号连接起来。concat()却函数没有提供这样的功能。
groupby子句
groupby子句将结果集分为若干个组,使用聚合函数可以对每个组内的数据进行信息统计,有时需要对各个组进行汇总运算,则需要在每个分组后加上一条汇总记录。
//统计每一年出生的人数SELECTsan_wujiang.`出生年`,COUNT(`出生年`)AS出生人数FROMsan_wujiangGROUPBYsan_wujiang.`出生年`
合并结果集
使用union可以将多个slct语句的查询结果集组合成一个结果集。
SELECTsan_wujiang.`出生年`FROMsan_wujiangUNIONSELECTsan_wujiang.`出生年`FROMsan_wujiang
字段列表1与字段列表2的字段个数必须相同,且具有相同的数据类型。合并产生的新结果集的字段名与字段列表1中的字段名对应。
union与unionall的区别
当使用union时,MySQL会筛选掉slct结果集中重复的记录(在结果集合并后会对新产生的结果集进行排序运算,效率稍低)。而使用unionall时,MySQL会直接合并两个结果集,效率高于union。如果可以确定合并前的两个结果集中不包含重复的记录,建议使用unionall。
子查询
如果一个slct语句能够返回单个值或者一列值,且该slct语句嵌套在另一个SQL语句中(例如slct语句、insrt语句、updat语句或者dlt语句)中,那么该slct语句称为子查询(也叫内层查询),包含子查询的SQL语句称为主查询(也叫外层查询)。为了标记子查询与主查询之间的关系,通常将子查询写在小括号内。子查询分为相关子查询与非相关子查询。
子查询一般用在主查询的wh子句或having子句中,与比较运算符或者逻辑运算符一起构成wh筛选条件或having筛选条件。
子查询与比较运算符
如果子查询返回单个值,则可以将一个表达式的值与子查询的结果集进行比较。子查询可以仅仅使用自己定义的数据源,也可以直接引用主查询中的数据源,但两者意义完全不同。
如果子查询中仅仅使用了自己定义的数据源,这种查询是非相关子查询,非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给主查询。如果子查询中使用了主查询的数据源,这种查询是相关子查询,此时主查询的执行与相关子查询的执行相互依赖。
子查询与in运算符
子查询经常与in运算符一起使用,用于将一个表达式的值与子查询返回的一列值进行比较,如果表达式的值是此列中的任何一个值,则条件表达式的结果为tru;否则为fals。
子查询与xists逻辑运算符
xists逻辑运算符用于检测子查询的结果集是否包含有记录,如果结果集中至少包含一条记录,则xists的结果为tru;否则为fals。在xists前面加上not时,与上述结果恰恰相反。
子查询与any运算符
any运算符通常与比较运算符一起使用。使用any运算符时,通过比较运算符将一个表达式的值与子查询返回的一列值逐一进行比较,若某次的比较结果为tru,则整个表达式的值为tru;否则为fals。any逻辑运算符的语法格式如下。
表达式比较运算符any(子查询)
举例来说:当比较运算符为大于号()时,“表达式any(子查询)”表示至少大于子查询结果集中的某一个值(或者说大于结果集中的最小值),那么整个表达式的结果为tru。
子查询与all运算符
all运算符通常与比较运算符一起使用。使用all运算符时,通过比较运算符将一个表达式的值与子查询返回的一列值逐一进行比较,若每次的比较结果都为tru,则整个表达式的值为tru;否则为fals。any逻辑运算符的语法格式如下。
表达式比较运算符all(子查询)
当比较运算符为大于号()时,“表达式all(子查询)”表示大于子查询结果集中的任何一个值(或者说大于结果集中的最大值),那么整个表达式的结果为tru。
使用正则表达式模糊查询
与lik运算符相似,正则表达式主要用于判断一个字符串是否与给定的模式匹配,但正则表达式的模式匹配功能比lik运算符的模式匹配功能更为强大,且更加灵活。使用正则表达式进行模糊查询时,需要使用gxp关键字。
字段名[not]gxp[binary]正则表达式
正则表达式由一些普通字符和一些元字符构成,普通字符包括大写字母、小写字母和数字,而元字符具有特殊的含义。在最简单的情况下,一个正则表达式是一个不包含元字符的字符串。
例如检索含有曹的武将姓名,可以使用下面的SQL语句。
slct*fromsan_wujiangwhsan_wujiang.`姓名`gxp曹;
例如检索以宇结尾的武将姓名,可以使用下面的SQL语句。
slct*fromsan_wujiangwhsan_wujiang.`姓名`gxp宇$;
例如检索以诸开头,以亮结尾的武将姓名,可以使用下面的SQL语句。
slct*fromsan_wujiangwhsan_wujiang.`姓名`gxp^诸.*亮$;
常用的元字符