六、MySQL查询数据
数据库管理系统的一个最重要的功能就是数据查询,数据查询不应只是简单查询数据库中存储的数据,还应该根据需要对数据库进行筛选,以及确定数据以什么样的格式显示。MySQL提供了功能强大、灵活的语句来实现这些操作。
一、基本查询语句
MySQL从数据表中查询数据的基本语句为SELECT语句。SELECT语句的基本格式为:
SELECT {*|<字段列表>} [ FROM 表1,表2,... WHERE <表达式> [GROUP BY <group by definition>] [HAVING <expression> [<operator> <expression>]] [ORDER BY <order by definition>] [LIMIT [<offset>,] <row count>] ] SELECT [字段1,字段2,...,字段n] FROM [表或视图] WHERE [查询条件];
其中,各条子句的含义如下:
(1){*|<字段列表>}包含星号通配符选择字段列表,表示查询的字段,其中字段列至少包含一个字段名称,如果要查询多个字段,多个字段之间用逗号隔开,最后一个字段后不要加逗号。
(2)FROM <表1>,<表2>...,表1和表2表示查询数据的来源,可以是单个或者多个。
(3)WHERE子句是可选项,如果选择该项,将限定查询行必须满足的查询条件。
(4)GROUP BY <字段>,该子句告诉MySQL如何显示查询出来的数据,并按照指定的字段分组。
(5)[ORDER BY <字段>],该子句告诉MySQL按什么样的顺序显示查询出来的数据,可以进行的排序有:升序(ASC)、降序(DESC)。
(6)[LIMIT [<offset>,] <row count>],该子句告诉MySQL每次显示查询出来的数据条数。
二、单表查询
单表查询是指从一张表数据中查询所需的数据。主要查询方式有:查询所有字段、查询指定字段、查询指定记录、查询空值、多条件的查询、对查询结果进行排序等。
2.1 查询所有字段
SELECT查询记录最简单的形式是从一个表中检索所有记录,实现的方法是使用星号(*)通配符指定查找所有列的名称。语法格式如下:
SELECT * FROM 表名
2.2 查询指定字段
2.2.1 查询单个字段
查询表中的某一字段,语法格式为:
SELECT 列名 FROM 表名
2.2.2 查询多个字段
使用SELECT声明,可以获取多个字段下的数据,只需要在关键字SELECT后面指定要查找的字段的名称,不同字段名称之间用逗号(,)分隔开,最后一个字段后面不需要加逗号,语法格式如下:
SELECT 字段名1,字段名2,...,字段名n FROM 表名
提示:MySQL中的SQL语句是不区分大小写的,因此SELECT和select作用是相同的,但是,许多开发人员习惯将关键字使用大写,而数据列和表名使用小写,这样写出来的代码更容易阅读和维护。
2.3 查找指定记录
数据库中包含大量的数据,根据特殊要求,可能只需要查询表中的指定数据,即对数据进行过滤。在SELECT语句中,通过WHERE子句可以对数据进行过滤,语法格式为:
SELECT 字段名1,字段名2,...,字段名3 FROM 表名 WHERE 查询条件
操作符 | 说明 |
= | 相等 |
<>,!= | 不相等 |
< | 小于 |
<= | 小于或者等于 |
> | 大于 |
>= | 大于或者等于 |
BETWEEN | 位于两值之间 |
2.4 带IN关键字的查询
IN操作符用来查询满足指定范围内的条件的记录,使用IN操作符,将所有检索条件用括号括起来,检索条件之间用逗号分隔开,只要满足条件范围内的一个值即为匹配项。
相反的,可以使用关键字NOT来检索不在条件范围内的记录。
2.5 带BETWEEN AND的范围查询
BETWEEN AND用来查询某个范围内的值,该操作符需要两个参数,即范围的开始值和结束值,如果字段值满足指定的范围查询条件,则这些记录被返回。
BETWEEN AND操作符前可以加关键字NOT,表示指定范围之外的值,如果字段值不满足指定的范围内的值,则这些记录被返回。
2.6 带LIKE的字符匹配查询
如果要查找所有包含字符“ge”的数据,简单的比较操作在这里已经行不通了,在这里,需要使用通配符进行匹配查找,通过创建查找模式对表中的数据进行比较。执行这个任务的关键字是LIKE。
通配符是一种在SQL的WHERE条件子句中拥有特殊意思的字符,SQL语句支持多种通配符,可以和LIKE一起使用的通配符有‘%’和‘_’。
(1)百分号通配符‘%’,匹配任意长度的字符,甚至包括零字符。
(2)下划线通配符‘_’,一次只能匹配任意一个字符。
2.7 查询空值
数据表创建的时候,设计者可以指定某列中是否可以包含空值(NULL)。空值不同于0,也不同于空字符串。空值一般表示数据未知、不适用或将在以后添加数据。在SELECT语句中使用IS NULL子句,可以查询某字段内容为空的记录。
SELECT 字段名 FROM 表名 WHERE 字段名 IS NULL;
与IS NULL相反的是NOT IS NULL,该关键字查找字段不为空的记录。
2.8 带AND的多条件查询
使用SELECT查询时,可以增加查询的限制条件,这样可以使查询的结果更加精确。MySQL在WHERE子句中使用AND操作符限定只有满足所有查询条件的记录才会被返回。可以使用AND连接两个甚至多个查询条件,多个条件表达式之间用AND分开。
SELECT * FROM 表名 WHERE 条件1 AND 条件2 AND 条件3...
2.9 带OR的多条件查询
与AND相反,在WHERE声明中使用OR操作符,表示只需要满足其中一个条件的记录即可返回。OR也可以连接两个甚至多个查询条件,多个条件表达式之间用OR分开。
SELECT * FROM 表名 WHERE 条件1 OR 条件2 OR 条件3...
2.10 查询结果不重复
有时,出于对数据分析的要求,需要消除重复的记录值,如何使查询结果没有重复呢?在SELECT语句中,可以使用DISTINCT关键字指示MySQL消除重复的记录值。语法格式为:
SELECT DISTINCT 字段名 FROM 表名;
2.11 对查询结果排序
从前面的查询结果发现,有些字段的值是没有任何顺序的,MySQL可以通过在SELECT语句中使用ORDER BY子句,对查询结果进行排序。
2.11.1 单列排序
SELECT 字段名 FROM 表名 ORDER BY 字段名
2.11.2 多列排序
SELECT 字段名1,字段名2 FROM 表名 ORDER BY 字段名1,字段名2
在对多列进行排序的时候,首先排序的第一列必须有相同的列值,才会对第二列进行排序。如果第一列数据中所有值都是唯一的,将不再对第二列进行排序。
2.11.3 指定排序方向
SELECT 字段名 FROM 表名 ORDER BY 字段名 [DESC|ASC]
DESC表示降序排序,ASC表示升序排序,它们只对其前面的列起作用,如果要对每一列都设置排序方式,必须在每一列的后面加上DESC/ASC,默认的排序方式为升序排序(ASC)。
2.12 分组查询
分组查询是对数据按照某个或多个字段进行分组,MySQL中使用GROUP BY关键字对数据进行分组,基本语法形式为:
[GROUP BY 字段] [HAVING <条件表达式>]
字段值为进行分组时所依据的列名称;“HAVING <条件表达式>”指定满足表达式限定条件的结果将被显示。
2.12.1 创建分组
GROUP BY关键字通常和集合函数一起使用,例如:MAX()、MIN()、COUNT()、SUM()、AVG()。例如,要返回每个水果供应商提供的水果种类,这时就要在分组过程中用到COUNT()函数,把数据分为多个逻辑组,并对每个组进行集合计算。
2.12.2 使用HAVING过滤分组
GROUP BY可以和HAVING一起限定显示记录所需满足的条件,只有满足条件的分组才会被显示。
提示:HAVING关键字与WHERE关键字都是用来过滤数据,两者有什么区别吗?其中重要的一点是,HAVING在数据分组之后进行过滤来选择分组,而WHERE在分组之前用来选择记录。另外WHERE排出的分组不再包括在分组中。
2.12.3 在GROUP BY子句中使用WITH ROLLUP
使用WITH ROLLUP关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所有记录的总和,即统计记录数量。
2.12.4 多字段分组
使用GROUP BY可以对多个字段进行分组,GROUP BY关键字后面跟需要分组的字段,MySQL根据多字段的值来进行层次分组,分组层次从左到右,即先按第1个字段分组,然后第1个字段值相同的记录中,再根据第2个字段的值进行分组……以此类推。
2.12.5 GROUP BY和ORDER BY一起使用
某些情况下需要对分组进行排序,ORDER BY用来对查询的记录排序,如果和GROUP BY一起使用可以完成对分组的排序。
提示:当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序。即ROLLUP和ORDER BY是相互排斥的。
2.13 使用LIMIT限制查询结果的数量
SELECT返回所有匹配的行,有可能是表中所有的行,如仅仅需要返回第一行或者前几行,使用LIMIT关键字,基本语法格式如下:
LIMIT [位置偏移量,] 行数
三、使用聚合函数查询
有时候并不需要返回实际表中的数据,而只是对数据进行总结。MySQL提供一些查询功能,可以对获取的数据进行分析和报告。这些函数的功能有:计算数据表中记录行数的总数、计算某个字段列下数据的总和,以及计算表中某个字段下的最大值、最小值或者平均值。
函数 | 作用 |
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行数 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列的和 |
四、连接查询
连接是关系数据库模型的主要特点。连接查询时关系数据库中最主要的查询,主要包括内连接、外连接等。通过连接运算符可以实现多个表查询。在关系型数据库管理系统中,表建立时各数据的之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当查询数据时,通过连接操作查询出存放在多个表中的不同实体的信息。当两个或多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。
4.1 内连接查询
内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新纪录,也就是说,在内连接查询中,只有满足条件的记录才能出现在结果关系中。
在内连接查询语句中,两个表之间的关系通过INNER JOIN指定。使用这种语法的时候,连接的条件使用ON子句给出而不是WHERE,ON和WHERE后面指定的条件相同。
提示:使用WHERE子句定义连接条件比较简单明了,而INNER JOIN语法是ANSI SQL的标准规范,使用INNER JOIN连接语法能够确保不会忘记连接条件,而且,WHERE子句在某些时候回影响查询的性能。
如果在一个连接查询中,涉及的两个表都是同一个表,这种查询称为自连接查询。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一张表,但可以在逻辑上分为两张表。
4.2 外连接查询
外连接查询将查询多个表中相关联的行,内连接时,返回查询结果集合中的仅是符合查询条件和连接条件的行。但有时候需要包含没有关联的行中数据,即返回查询结果集合中的不仅包含符合连接条件的行,而且还包含左表(左外连接或左连接)、右表(右外连接或右连接)或两个连接表(全外连接)中的所有数据行。外连接分为左外连接或左连接和右外连接或右连接:
(1)LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。
(2)RIGHT JOIN(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。
4.2.1 LEFT JOIN(左连接)
左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列锁匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。
4.2.2 RIGHT JOIN(右连接)
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,左表将返回空值。
4.3 复合连接查询
复合条件连接查询是在连接查询的过程中,通过添加过滤条件,限制查询的结果,使查询的结果更加准确。
五、子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询,在SELECT中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。子查询常用的操作符有ANY(SOME)、ALL、IN、EXISTS。子查询可以添加到SELECT、UPDATE和DELETE语句中,而且可以进行多层嵌套。子查询中也可以使用比较运算符。
5.1 带ANY、SOME关键字的子查询
ANY和SOME关键字是同义词,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个查询条件,就返回一个结果作为外层查询的条件。
5.2 带ALL关键字的子查询
ALL关键字与ANY和SOME不同,使用ALL时需要同时满足所有内层查询的条件。
5.3 带EXISTS关键字的子查询
EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否有返回行,如果至少返回一行,那么EXISTS的结果为true,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是false,此时外层查询语句将不进行查询。
EXISTS关键字可以和条件表达式一起使用。
NOT EXISTS与EXISTS使用方法相同,返回的结果相反。
提示:EXISTS与NOT EXISTS的结果只取决于是否会返回行,而不取决于这些行的内容,所以这个子查询输入列表通常是无关紧要的。
5.4 带IN关键字的子查询
IN关键字进行子查询时,内层查询语句仅返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较操作。
SELECT语句中可以使用NOT IN关键字,其作用与IN相反。
提示:子查询的功能也可以通过连接查询来实现,但是子查询使得MySQL代码更容易阅读和编写。
六、合并查询结果
利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。UNION不使用关键字ALL,执行的时候删除重复的记录,所有返回的行都是唯一的;使用关键字ALL的作用是不删除重复行也不对结果进行自动排序。
UNION和UNION ALL的区别:使用UNION ALL的功能是不删除重复行,加上ALL关键字语句执行时所需要的资源少,所以尽可能使用它,因此知道有重复行但是想保留这些行,确定查询结果中不会有重复数据或者不需要去掉重复数据的时候,应当使用UNION ALL提高查询效率。
七、为表和字段取别名
7.1 为表取别名
当表名字很长或执行一些特殊查询时,为了方便操作或者需要多次使用相同的表时,可以为表指定别名,用这个别名替代表原来的名称。为表取别名的基本语法格式为:
表名 [AS] 别名
在为表取别名的时候,要保证不能与数据库中的其他表的名称冲突。
7.2 为字段取别名
在有些情况下,显示的列的名称会很长或者名称不够直观,MySQL可以指定列别名,替换字段或表达式。为字段取别名的基本语法格式为:
列名 [AS] 列别名
表别名只在执行查询的时候使用,并不在返回结果中显示,而列别名定义之后,将返回给客户端显示,显示的结果字段为字段列的别名。
八、使用正则表达式查询
正则表达式通常被用来检索或替换那些符合某个模式的文本内容,根据指定的匹配模式匹配文本中符合要求的特殊字符串。正则表达式强大而且灵活,可以应用于非常复杂的查询。
MySQL中使用REGEXP关键字指定正则表达式的字符匹配模式。
WHERE 字段名 REGEXP 正则表达式