MySQL DQL 数据查询
文章目录
- 1.SELECT 语句
- 2.SELECT 子句
- 3.FROM 子句
- 4.WHERE 子句
- 5.GROUP BY 子句
- 6.HAVING 子句
- 7.ORDER BY 子句
- 8.LIMIT 子句
- 9.DISTINCT 子句
- 10.UNION 子句
- 11.查看数据表记录数
- 12.检查查询语句的执行效率
- 13.查看 SQL 执行时的警告
- 14.查看自增主键最大值
- 参考文献
1.SELECT 语句
MySQL 的 SELECT 语句用于从数据库表中检索数据。功能强大,语句结构复杂多样。不过基本的语句格式像下面这个样子。
SELECT[列名称]FROM[表名称]WHERE[条件]一个完整的 SELECT 语句包含一些可选的子句。SELECT 语句定义如下:
SELECTclause[FROMclause][WHEREclause][GROUPBYclause][HAVINGclause][ORDERBYclause][LIMITclause]- SELECT 子句是必选的,其它子句是可选的。
一个 SELECT 可以在不引用任何表的情况下进行计算,也就是没有其他任何字句,只有 SELECT 子句。
SELECT1+1ASsum;+-----+|sum|+-----+|2|+-----+- 一个 SELECT 语句中,子句的顺序是固定的。如 GROUP BY 子句不会位于 WHERE 子句前面。
- SELECT 语句不同子句的执行顺序:
开始>FROM子句>WHERE子句>GROUPBY子句>HAVING子句>SELECT子句>ORDERBY子句>LIMIT子句>最终结果每个子句执行后都会产生一个中间数据结果,即所谓的临时视图,供接下来的子句使用,如果不存在某个子句则跳过。
需要注意的是,不同的数据库管理系统可能会有一些差异,但一般情况下,上述顺序适用于大多数SQL查询。
MySQL 和标准 SQL 执行顺序基本是一样的。
2.SELECT 子句
SELECT 子句用于指定要选择的列或使用表达式生成新的值。
对于所选数据,还可以添加一些修饰,比如使用 DISTINCT 关键字用于去重。
一个完整的 SELECT 子句组成如下。
SELECT[ALL|DISTINCT|DISTINCTROW][HIGH_PRIORITY][STRAIGHT_JOIN][SQL_SMALL_RESULT][SQL_BIG_RESULT][SQL_BUFFER_RESULT][SQL_NO_CACHE][SQL_CALC_FOUND_ROWS]select_expr[,select_expr]...[into_option]into_option: {INTOOUTFILE'file_name'[CHARACTERSETcharset_name]export_options|INTODUMPFILE'file_name'|INTOvar_name[,var_name]...}其中 select_expr 是必选的,表示要查询的列、表达式或使用 * 表示所有列。
SELECT*FROMt1INNERJOINt2...可以对列使用函数进行运算,并使用 AS 关键字对结果列命名(AS 是可选的,可以省略)。
SELECTAVG(score)ASavg_score,t1.*FROMt1...# 或SELECTAVG(score)avg_score,t1.*FROMt1...3.FROM 子句
FROM 子句指示要从中检索行的表。如果为多个表命名,则执行连接。对于指定的每个表,您可以选择指定一个别名。
FROMtable_references[PARTITIONpartition_list]SELECT 支持显式分区选择,使用 PARTITION 子句,在 table_references 表的名称后面跟着一个分区或子分区列表(或两者都有)在这种情况下,只从列出的分区中选择行,而忽略表的任何其他分区。关于分区可参考 Chapter 24 Partitioning。
4.WHERE 子句
如果给定 WHERE 子句,则指示行必须满足的一个或多个条件才能被选中。where_condition 是一个表达式,对于要选择的每一行,其计算结果为 true 才会被选择。如果没有 WHERE 子句,将选择所有行。
[WHERE condition]下面的运算符可在 WHERE 子句的条件表达式中使用。
| 运算符 | 描述 |
|---|---|
| = | 等于 |
| != 或 <> | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| BETWEEN AND | 在某个范围内(闭区间) |
| LIKE | 搜索某种模式 |
| AND | 多个条件与 |
| OR | 多个条件或 |
(1)WHERE IN 的用法
IN 在 WHERE 子句中的用法主要有两种:
- IN 后面是子查询产生的记录集,注意,子查询结果数据列只能有一列且无需给子查询的结果集添加别名。
SELECT*FROMtbl_name1WHEREcol_name1IN(SELECTcol_name2FROMtbl_name2);- IN 后面是数据集合。
SELECT * FROM tbl_name WHERE col_name IN ('foo', 'bar', 'baz', 'qux');注意:如果数据类型是字符串,一定要将字符串用单引号引起来。
5.GROUP BY 子句
GROUP BY 子句是 SQL 中用于对数据进行分组聚合的核心功能。它将查询结果按照一个或多个列的值分成不同的组,然后对每一组应用聚合函数(如 SUM、AVG、COUNT、MAX、MIN 等),最终每个组返回一行汇总结果。
核心作用:
- 数据分组:将具有相同值的记录归类到同一组中;
- 为聚合计算划定范围:聚合函数会在每个分组内独立计算,而不是针对整个表;
- 减少结果集行数:原始表中的多行数据,按分组条件压缩成一行汇总结果。
基本语法:
SELECT分组列1,分组列2,聚合函数(列名)AS别名FROM表名WHERE条件GROUPBY分组列1,分组列2;执行顺序:WHERE → GROUP BY → 聚合计算 → HAVING → SELECT → ORDER BY。
示例:
-- 选择发起加好友请求次数超过10次的 QQ(uin),被加方(to_uin)只会显示第一个SELECTuin,to_uin,count(*)AScntfrominner_raw_add_friend_20170514GROUPBYuinHAVINGcnt>10;如果指定多列,使用逗号分隔。
GROUPBYcol1,col2,...注意:GROUP BY 子句中的数据列应该是 SELECT 指定的所有数据列,除非这列用于聚合函数。但是,如果 SELECT 指定的数据列,没有用于聚合函数也不在 GROUP BY 子句中,按理说会报错,但是 MySQL 会选择第一条显示在结果集中。
6.HAVING 子句
HAVING 和 WHERE 子句一样,用于指定选择条件。但 HAVING 和 WHERE 子句的用法上却有明显的区别。
- 作用的对象不同。
WHERE 作用于表和视图,HAVING 作用于组。
# 查询 QQ 3585076592 和 3585075773 在 20170514 当天加好友请求次数且请求次数>10SELECTuin,count(*)AScntFROMinner_raw_add_friend_20170514WHEREuin=3585076592ORuin=3585075773GROUPBYuinHAVINGcnt>10;- 作用的阶段不同。
WHERE 在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算),而 HAVING 在分组和聚集之后选取分组。因此,WHERE 子句不能包含聚集函数,因为试图用聚集函数判断哪些行输入给聚集运算是没有意义的。 相反,HAVING 子句一般包含聚集函数。当然,也可以使用 HAVING 对结果集进行筛选,但不建议这样做,同样的条件可以更有效地用于 WHERE 阶段。
# 查询指定 QQ 加好友请求信息(where作用于输入阶段的数据集)SELECT*FROMinner_raw_add_friend_20170514WHEREuin=3585078528;# 作用等同于 WHERE, 但 HAVING 作用于结果阶段的结果集SELECT*FROMinner_raw_add_friend_20170514HAVINGuin=3585078528;7.ORDER BY 子句
ORDER BY 子句用于根据指定的列对结果集进行排序。
[ORDERBY{col_name|expr|position}[ASC|DESC],...[WITH ROLLUP]]ORDER BY 语句默认按照升序 ASC(ascend)对记录进行排序。如果希望按照降序排序,可以使用 DESC(descend)关键字,随机使用随机数函数RAND()。
在指定待排序的列时,不建议使用列位置(从1开始),因为该语法已从SQL标准中删除。
比如以 QQ 号码降序排序。
SELECT*FROMinner_raw_add_friend_20170514ORDERBYuinDESC;8.LIMIT 子句
LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。
[LIMIT{[offset,]row_count|row_countOFFSEToffset}]LIMIT 接受一个或两个数值参数。参数必须是一个整数常量。如果给定两个参数,有两种用法。
offset,row_count# 或row_countOFFSEToffsetoffset 为返回记录行的开始偏移量,从 0 开始,row_count 为返回记录行的最大数目。
只给一个参数,表示返回记录行的 Top 最大行数,起始偏移量默认为 0。
返回从起始偏移量开始,返回剩余所有的记录,可以使用一些值很大的第二个参数。如检索所有从第 96 行到最后一行。
SELECT*FROMtblLIMIT95,18446744073709551615;注意,MySQL目前不支持使用 -1 表示返回从偏移量开始剩余的所有记录,即下面的写法是错误的:
SELECT*FROMtblLIMIT95,-19.DISTINCT 子句
DISTINCT 关键字用于查询结果中去除重复的行,只返回唯一的行。
(1)利用 DISTINCT 结合 COUNT() 函数可以统计不重复记录的数量。
# 选择每一个 QQ 发起加好友请求涉及到的不同的 QQ 数SELECTuin,count(distinctto_uin)cFROMadd_friendGROUPBYuin;(2)DISTINCT 用于选择不同的记录,且只能放在所选列的开头,作用于紧随其后的所有列。
# 查询 uin 和 to_uin 不重复的加好友请求SELECTDISTINCTuin,to_uinFROMadd_friend;# 示例数据表uin to_uin10000123456100001212121000112121210001131313# 结果集uin to_uin10000123456100001212121000112121210001131313如果想使 DISTINCT 的功能作用于第二列的 to_uin,使用 DISTINCT 是无望了,因为 MySQL 语法尚不支持,可以使用 GROUP BY 取而代之。
SELECTuin,to_uinFROMadd_friendWHEREGROUPBYto_uin;# 结果集uin to_uin100001234561000012121210001131313该奇技淫巧只能用在 MySQL,因为标准的 SQL 语法规定非聚合函数中的列一定要在 GROUP BY 子句中。MySQL 规定,当非聚合函数中的列不存在于 GROUP BY 子句中,则选择每个分组的第一行。
(3)COUNT DISTINCT 统计符合条件的记录数量。
如果像对符合条件的记录进行 COUNT DISTINCT,那么如何添加条件呢?
参见 MySQL distinct count if conditions unique,可以使用下面的方法。
COUNT(DISTINCTCASEWHEN条件THEN字段END)参见 mysql count if distinct,也可以使用下面这种方法。
COUNT(DISTINCTcol_name1,IF(col_name2=1,true,null))10.UNION 子句
UNION 的作用是将两次或多次查询结果纵向合并起来。
query_expression_bodyUNION[ALL|DISTINCT]query_block[UNION[ALL|DISTINCT]query_expression_body][...]下面是一个示例。
mysql>SELECT1,2;+---+---+|1|2|+---+---+|1|2|+---+---+mysql>SELECT'a','b';+---+---+|a|b|+---+---+|a|b|+---+---+mysql>SELECT1,2UNIONSELECT'a','b';+---+---+|1|2|+---+---+|1|2||a|b|+---+---+使用 UNION 需要注意以下几点。
(1)UNION 的使用条件
UNION 只能作用于结果集,不能直接作用于原表。结果集的列数相同就可以,即使字段类型不相同也可以使用。值得注意的是 UNION 后字段的名称以第一条 SQL 为准。
(2)UNION 与 UNION ALL 的区别
UNION 用于合并两个或多个 SELECT 语句的结果集,并消去合并后的重复行。UNION ALL 则保留重复行。
(3)关于 UNION 的排序
有两张表,内容如下:
# table1 uin nickname 10001 monkey 10002 monkey king # table2 uin nickname 20000 cat 20001 dog对两个结果集按照 uin 进行降序排序后再联合。
(SELECT*FROMtable1ORDERBYuinDESC)UNION(SELECT*FROMtable2ORDERBYuinDESC);uin nickname10001monkey10002monkey king20000cat20001dog可以发现,内层排序没有发生作用,那现在试试在外层排序。
SELECT*FROMtable1UNIONSELECT*FROMtable2ORDERBYuinDESC;uin nickname20001dog20000cat10002monkey king10001monkey可见外层排序发生了作用。那是不是内层排序就没有用了呢,其实换个角度想想内层先排序,如果外层又排序,明显内层排序显得多余,所以 MySQL 优化了 SQL 语句,不让内层排序起作用。要想内层排序起作用,必须要使内层排序的结果能影响最终的结果,如加上 LIMIT。
(SELECT*FROMtable1ORDERBYuinDESCLIMIT2)UNION(SELECT*FROMtable2ORDERBYuinDESCLIMIT2);uin nickname10002monkey king10001monkey20001dog20000cat此外,UNION 与 JOIN 在使用时,有一个本质区别我们必须知道。
UNION 只能作用于 SELECT 结果集,不能直接作用于数据表,而 JOIN 则恰恰相反,只作用于数据表,不能直接作用于 SELECT 结果集(可以将 SELECT 结果集指定别名作为派生表)。
11.查看数据表记录数
查看数据表行数有多种方法。
- 使用 COUNT(*)
SELECTCOUNT(*)FROMtbl_name;对于 MyISAM 数据表很快,建议使用,因为 MyISAM 数据表事先将行数缓存起来,可直接获取。InnoDB 数据表不建议使用,当数据表行数过大时,因需要扫描全表,查询较慢。
- 查看系统表 information_schema.TABLES
SELECTtable_rowsFROMinformation_schema.TABLESWHERETABLE_SCHEMA='db_name'ANDTABLE_NAME='tbl_name';information_schema 是 MySQL 中的一个系统数据库,它包含了关于数据库、表、列等元数据信息。可以通过查询 information_schema.TABLES 表可以获取指定数据表的记录数。
- 使用 SHOW TABLE STATUS 命令
SHOWTABLESTATUSLIKE'tbl_name';需要注意的是,SHOW TABLE STATUS 命令返回的行数是一个近似值,并不是实时的准确值。这是因为 MySQL 在某些情况下会对行数进行估算,而不是实时计算。如果需要准确的行数,建议使用 COUNT(*) 函数或查询 information_schema.TABLES 视图。
12.检查查询语句的执行效率
EXPLAIN 是一个用于查询优化的工具,它可以提供有关 SELECT 查询的执行计划的详细信息。通过使用 EXPLAIN 命令,可以了解 MySQL 是如何执行查询的,包括使用的索引、连接类型、扫描的行数等。
{EXPLAIN|DESCRIBE|DESC} select_statement;EXPLAIN 命令的输出结果包含以下列:
id:查询的标识符,用于标识查询中的每个步骤。 select_type:查询的类型,如 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等。 table:查询涉及的表。 partitions:查询涉及的分区。 type:访问表的方式,如 ALL(全表扫描)、INDEX(使用索引扫描)、RANGE(范围扫描)等。 possible_keys:可能使用的索引。 key:实际使用的索引。 key_len:使用的索引的长度。 ref:与索引比较的列或常量。 rows:扫描的行数。 filtered:过滤的行百分比。 Extra:额外的信息,如使用了临时表、使用了文件排序等。13.查看 SQL 执行时的警告
SHOW WARNINGS 是一个用于查看最近一次执行的语句产生的警告信息的命令。在 MySQL 中,警告(Warning)是一种表示潜在问题或异常情况的消息,它不会导致语句的执行失败,但可能会影响到查询结果或性能。
SHOWWARNINGS;SHOW WARNINGS 命令的输出结果包含以下列:
Level:警告的级别,如 Warning、Note 等。 Code:警告的代码。 Message:警告的具体消息。通过查看警告信息,可以了解到语句执行过程中可能存在的问题或异常情况,如截断数据、丢失数据等。根据警告信息,可以进行相应的调整和处理,以确保查询的正确性和性能。
14.查看自增主键最大值
- 使用 MAX 函数。
SELECTMAX(id)FROMyour_table_name;- 查看表状态
SHOWTABLESTATUSLIKE'your_table_name';在查询结果中,您可以查找 Auto_increment 列,它将显示自增主键的下一个值。
参考文献
MySQL 8.0 Reference Manual :: 13.2.13 SELECT Statement
MySQL 8.0 Reference Manual :: 13.2.18 UNION Clause
MySQL 8.0 Reference Manual :: 13.2.13.2 JOIN Clause
MySQL 8.0 Reference Manual :: 13.8.2 EXPLAIN Statement
8.8.1 Optimizing Queries with EXPLAIN
