MySQL 系列教程之(七)DQL:从 select 开始
从 SELECT 开始
检索单个列
select name from user
如果没有明确排序查询结果(下一章介绍),则返回的数据的顺序没有特殊意义。
返回数据的顺序可能是数据被添加到表中的顺序,也可能不是。只要返回相同数目的行,就是正常的
检索多个列
select id,name,age,sex from user
在选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。
如果在最后一个列名后加了逗号,将出现错误。
检索所有列
select * from user
使用通配符 一般,除非你确实需要表中的每个列,否则最好别使用*通配符。
虽然使用通配符可能会使你自己省事,不用明确列出所需列,但检索不需要的列通常会降低检索和应用程序的性能。
使用通配符有一个大优点。由于不明确指定列名(因为星号检索每个列),所以能检索出名字未知的列。
检索不同的行 DISTINCT
select distinct classid from user
DISTINCT 关键字,顾名思义,此关键字指示 MySQL 只返回不同的值
DISTINCT 关键字应用于所有列而不仅是前置它的列。
如果给出 SELECT DISTINCT vend_id, prod_price,除非指定的两个列都不同,否则所有行都将被检索出来
+### 限制结果 LIMIT
select * from user limit 3,4
LIMIT 3, 4 的含义是从行 3 开始的 4 行.(跳过前 3 行,取 4 行)
替代语法 LIMIT 4 OFFSET 3 意为从行 3 开始取 4 行,就像 LIMIT 3, 4 一样。
使用完全限定的表名
select name from user
select user.name from user
select user.name from itxdl.user
排序数据 ORDER BY
select * from user order by age
默认查询出的数据,并不是随机排序的,如果没有指定排序,数据一般将以它在底层表中出现的顺序显示
关系数据库设计理论认为,如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有意义
通常,ORDER BY 子句中使用的列将是为显示所选择的列。
但是,实际上并不一定要这样,用非检索的列排序数据是完全合法的。
按多个列排序
select * from user order by classid,age
在需要对多列数据进行排序时,使用逗号分隔列名,并会按照前后顺序依次对比排序
order by
的排序默认升序,可以使用 DESC 设置降序排列
select * from user order by classid,age DESC
以上语句就是先对 classid 进行升序排序,然后在结果中对 age 进行降序排序
注意
ORDER BY 子句的位置 在给出 ORDER BY 子句时,应该保证它位于 FROM 子句之后。
如果使用 LIMIT,它必须位于 ORDER BY 之后。使用子句的次序不对将产生错误消息
过 滤 数 据 WHERE
数据库表一般包含大量的数据,很少需要检索表中所有行。
通常只会根据特定操作或报告的需要提取表数据的子集。
只检索所需数据需要指定搜索条件(search criteria),搜索条件也称为过滤条件(filtercondition)。在 SELECT 语句中,数据根据 WHERE 子句中指定的搜索条件进行过滤。
select name from user where age = 22
在同时使用 ORDER BY 和 WHERE 子句时,应该让 ORDER BY 位于 WHERE 之后,否则将会产生错误
WHERE 子句操作符
组合 WHERE 子句
MySQL 允许给出多个 WHERE 子句。
这些子句可以两种方式使用:以 AND 子句的方式或 OR 子句的方式使用。也称为逻辑操作符
select name from user where age = 22 and sex = 'm'
AND 用在 WHERE 子句中的关键字,用来指示检索满足所有给定条件的行
select name from user where age = 22 or sex = 'm'
OR 用来表示检索匹配任一给定条件的行
AND 与 OR
WHERE 可包含任意数目的 AND 和 OR 操作符。允许两者结合以进行复杂和高级的过滤。
但是,组合 AND 和 OR 带来了一个有趣的问题。
例如:我需要在数据库中查询出 18 期或 19 期的学员,并且要求是女生
select name from user where classid=18 or classid =19 and sex='m'
以上语句不会按照预期检索出正确的数据,问题出在哪里?
原因在于计算的次序。SQL 在处理 OR 操作符前,优先处理 AND 操作符。
当 SQL 看到上述 WHERE 子句时,它理解是 19 期班级的所有女生,或者 18 期的所有学员,而不分性别。换句话说,由于 AND 在计算次序中优先级更高,操作符被错误地组合了
因此想要解决就需要提升优先级,使用圆括号明确地分组相应的操作符
select name from user where (classid=18 or classid =19) and sex='m'
因为圆括号具有较 AND 或 OR 操作符高的计算次序,数据库首先过滤圆括号内的 OR 条件。
这时,SQL 语句变成了获取 18 期或 19 期的学员并且要求是女生
IN 与 NOT
IN 操作符用来指定条件范围,范围中的每个条件都可以进行匹配。
select name from user where classid in (18,19)
IN WHERE 子句中用来指定要匹配值的清单的关键字,功能与 OR 相当
为什么要使用 IN 操作符?其优点具体如下。
在使用长的合法选项清单时,IN 操作符的语法更清楚且更直观。在使用 IN 时,计算的次序更容易管理(因为使用的操作符更少)。IN 操作符一般比 OR 操作符清单执行更快。IN 的最大优点是可以包含其他 SELECT 语句,使得能够更动态地建立 WHERE 子句。
NOT WHERE 子句中用来否定后跟条件的关键字
select name from user where classid not in (18,19)
为什么使用 NOT?对于简单的 WHERE 子句,使用 NOT 确实没有什么优势。
但在更复杂的子句中,NOT 是非常有用的。
例如,在与 IN 操作符联合使用时,NOT 使找出与条件列表不匹配的行非常简单。
LIKE 与通配符
前面介绍的所有操作符都是针对已知值进行过滤的。
但是,这种过滤方法并不是任何时候都好用。
例如,怎样搜索产品名中包含文本 anvil 的所有产品?用简单的比较操作符肯定不行,必须使用通配符。
为在搜索子句中使用通配符,必须使用 LIKE 操作符。
LIKE 指示 MySQL,后跟的搜索模式利用通配符匹配而不是直接相等匹配进行比较。
百分号(%)通配符 在搜索串中,%表示任何字符出现任意次数
下划线(_)通配符 下划线的用途与 %一样,但下划线只匹配单个字符而不是多个字符
使用通配符的技巧
了解下 MySQL 的正则 REGEXP
字段的拼接,别名,计算
存储在数据库表中的数据一般不是应用程序所需要的格式。下面举几个例子
如果想在一个字段中既显示公司名,又显示公司的地址,但这两个信息一般包含在不同的表列中。城市、州和邮政编码存储在不同的列中(应该这样),但邮件标签打印程序却需要把它们作为一个恰当格式的字段检索出来。列数据是大小写混合的,但报表程序需要把所有数据按大写表示出来。物品订单表存储物品的价格和数量,但不需要存储每个物品的总价格(用价格乘以数量即可)。为打印发票,需要物品的总价格。需要根据表数据进行总数、平均数计算或其他计算
计算字段并不实际存在于数据库表中。计算字段是运行时在 SELECT 语句内创建的
拼接 Concat
vendors 表包含供应商名和位置信息。假如要生成一个供应商报表,需要在供应商的名字中按照 name(location)这样的格式列出供应商的位置
解决办法是把两个列拼接起来。在 MySQL 的 SELECT 语句中,可使用 Concat()函数来拼接两个列
select concat(vend_name,'(',vend_country')') from vendors order by vend_name
使用别名 AS
select concat(vend_name,'(',vend_country')') as vend_title from vendors order by vend_name
别名还有其他用途。常见的用途包括在实际的表列名包含不符合规定的字符(如空格)时重新命名它,在原来的名字含混或容易误解时扩充它,等等。
计算
函数的使用
与其他大多数计算机语言一样,SQL 支持利用函数来处理数据。
函数一般是在数据上执行的,它给数据的转换和处理提供了方便。
文本处理函数
日期和时间处理函数
数值处理函数
聚集函数的使用
我们经常需要汇总数据而不用把它们实际检索出来,为此 MySQL 提供了专门的函数。
使用这些函数,MySQL 查询可用于检索数据,以便分析和报表生成
确定表中行数(或者满足某个条件或包含某个特定值的行数)。获得表中行组的和。找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。
上述例子都需要对表中数据(而不是实际数据本身)汇总。
因此,返回实际表数据是对时间和处理资源的一种浪费
注意
在使用 count 时,如果指定列名,则指定列的值为空的行被忽略,但如果 COUNT()函数中用的是星号(*),则不忽略
数据分组 GROUP BY 与 HAVING
GROUP BY
SQL 聚集函数可用来汇总数据。这使我们能够对行进行计数,计算和与平均数,获得最大和最小值而不用检索所有数据
目前为止的所有计算都是在表的所有数据或匹配特定的 WHERE 子句的数据上进行的。
下面的例子返回供应商 1003 提供的产品数目:
select count(*) as num_prods from products where vend_id = 1003
但如果要返回每个供应商提供的产品数目怎么办?或者返回只提供单项产品的供应商所提供的产品,或返回提供 10 个以上产品的供应商怎么办?
此时就需要使用分组了,分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。
select vend_id,count(*) as num_prods from products group by vend_id
HAVING
除了能用 GROUP BY 分组数据外,MySQL 还允许过滤分组,规定包括哪些分组,排除哪些分组。
例如,可能想要列出至少有两个订单的所有顾客。为得出这种数据,必须基于完整的分组而不是个别的行进行过滤
事实上,目前为止所学过的所有类型的 WHERE 子句都可以用 HAVING 来替代。
唯一的差别是 WHERE 过滤行,而 HAVING 过滤分组。
select cust_id,count(*) as orders from orders group by cust_id;
select cust_id,count(*) as orders from orders group by cust_id having count(*) >= 2;
总结 SELECT 子句及其顺序
版权声明: 本文为 InfoQ 作者【若尘】的原创文章。
原文链接:【http://xie.infoq.cn/article/6f0e1b86355bc79e183ae3ff9】。文章转载请联系作者。
评论