数据查询语言DQL
where子句
where子句表示从给出的表数据中,取出其中符合条件的数据,通常都是对字段数据的判断。
where子句前面必须有from子句。虽然2者都可以省略,但有from可以没有where,但有where必须有from。
除了特殊的null,各种条件判断表达式返回的结果都是true或false(实际输出是1或0)。
而其中null其实也被当作false看待,因为是条件语句,所以终究只能说条件要么成立(true),要么不成立(false)。
where子句,相当于js中的if条件语句:其最终结果就是布尔值(true/false,1或0)
则最简单的情况是:
where true, where 1; where 1=1; 都表示true
where false, where 0; where 1<>1; 都表示false
where中可用的运算符
:
算术运算符: + , - , * , / , %
比较运算符: > >= < <= =(等于) <>(不等于) ==(等于,mysql扩展),!=(不等于,mysql扩展)
逻辑运算符: and(与) or(或) not(非) ,也可以用&&,||, !这3个符号,但不推荐。
布尔值的判断方式
:
布尔值:本质上,布尔值只是一位整数的“别名”,0表示false,非0表示true。
判断为true: XX is true
判断为fale: XX is false
XX应该是一个字段名,且其类型应该是一个整数。
实际应用中,布尔值判断很少用,因为可以直接使用数字大小。
空值的判断方式
:
判断为null: XX is null
判断为非空: XX is not null
XX应该是一个字段名
between语法
字段名XX between 值1 and 值2;
含义:字段XX的值在值1和值2之间(含该俩值),相当于:XX >=值1 and XX<=值2;
字段名XX not between 值1 and 值2;
含义:字段XX的值不在值1和值2之间(不含该俩值)。
in语法
in 语法
:
字段名XX in (值1,值2,...);
含义:XX等于其中所列出的任何一个值都算成立,相当于:XX = 值1 or XX = 值2 。
注意:其中的值1通常是“直接值”,但也可以是“查询结果值”。
not in语法
:
字段名 not in (值1,值2,...);
含义:返回不是值1,值2的数据.
like语法(模糊查找)
like语法形式:
字段名XX like '要查找字符';
含义:是“像什么一样”,用于从字符串中找出含有指定字符的数据,即所谓的“模糊查找”。
但这里字符,通常都不是直接写要找的字符,而是要附上一些表示模糊性的特殊字符。
说明
:
- like语法(模糊查找)用于对字符类型的字段进行字符匹配查找。
- 要查找的字符中,有2个特殊含义的字符:
- % 其含义是:代表任意个数的任意字符
- _ 其含义是:代表1个的任意字符
- 这里的字符,都是指现实中可见的一个“符号”,而不是字节。
- 实际应用中的模糊查找,通常都是这样:like ‘%关键字%’;
最常见的模糊查询:
还可以进一步结合(配合)使用:
如果要查找的字符中包含“%”或“_”,“’”,则只要对他们进行转义就可以:
要想匹配“%”和“_”这两个字符,就需要对其进行“转义”处理,比如:like ‘en_%’(表示以“en_”开头的任何记录), like ‘%__%’(表示以“%”结尾并前面至少有2个字符的记录,比如类似这样的:‘95%’, ‘超出18%’, ‘提升了50%’)。
like '%ab\%cd%' # 这里要找的是: 包含 ab%cd 字符的字符
like '_ab%' # 这里要找的是: _ab开头的字符
like '%ab\’cd%' # 这里要找的是: 包含 ab’cd 字符的字符
示例
:
where realName like '罗六奇';
# 找出realName等于'罗六奇'的记录,相当于where realName='罗六奇';所以like的这种用法几乎没有意义
where realName like '罗';
# 同上,找出realName='罗'的记录,实际可能没有这个记录,所以没有意义
where realName like '罗%';
# 这里“%”就是一个特殊字符,表示“任意个数的任意字符”,可以找出realName中以“罗”开头的名字。
where realName like '%罗%';
# 这种形式就是典型的“模糊查找”,可以找出realName字段中的任意位置含“罗”这个字符的记录
where realName like '罗_';
# 这里"_"就是一个特殊字符,表示“一个任意字符”,可以找出realName中以“罗”开头的两个字符的记录,例如罗弟,罗哥,罗叔,罗胖....,但找不出以下记录:罗六奇,罗哥哥,老罗,老罗永浩.。
group by 分组子句
使用形式
:
group by 字段名1 [排序方式ASC|DESC], 字段名2 [排序方式ASC|DESC],....
其中ASC或DESC表示对该分组的字段同时进行排序,可以省略,则默认是ASC(正序)。DESC表示倒序,跟order by的用法含义其实是一样的。
通常都只进行一个字段的分组。
什么是分组?
:
分组就是将数据以某个字段的值为“依据”,分到不同的“组别”里。
分组就是将一些数据以某种特征进行“归类”,比如一个班的学生信息,可以按省份进行分组,或按年龄分组,或按性别分组。分组完之后,结果集是某种“组”,可以理解为“小组”,其数量可能会急剧减少。比如全班60多个同学,如果按“省”分组,也许就只有10多个“组”了。如果按年龄分组,也许就只有7-8个组了(大约从20岁到26岁)。如果按性别分组,就只有2组了。即使公安部的全国10几亿的身份证信息,如果按年龄分组,最终也只能得到100多条的记录。group by 子句就是用于将前面取得的数据进行某种“分组”操作。
分组查询的select 部分有特殊的要求
:
出现在select中的字段名要么是group by中用过的字段名,要么是使用“聚合函数”处理过的字段名。
这是因为分组的结果数据是“一个一个组的信息”。比如有这样一个表:
,
则我们按商品品牌将其分组为:
常用聚合函数有:取平均值avg(), 取个数count(), 取总和sum(),取最大值max(), 取最小值min()。
举例(以此表为例)
:
# 找出产品中的所有品牌
select pinpai from product group by pinpai;
# 找出每个品牌的价格和,以及最高价
select pinpai, sum(price) as total,max(price) as maxPrice from product group by pinpai desc;
# 找出每种品牌的产品数量
select pinpai, count(pinpai) as shuliang from product group by pinpai;
分组结果
:
- 数据结果只能是“组”——没有数据本身的个体。
- 数据结果就可能“丢失”很多特性,比如没有性别,身高,姓名,等等。
- 实际上,结果中通常只剩下“组”作为整体的信息:
- 该组的本身依据值。
- 可能的值:组内成员的个数,组内某些字段的最大值,最小值,平均值,总和值。
- 其他字段,通常就不能用了。
- 如果是2个字段或以上分组,则其实是相当于对前一分组的组内,再进行后一依据的分组。
上述说明的结果,其实是反映在select语句中,select的“取出项”(输出项)就基本只剩下以上信息了,比如:
可见,在分组查询中,基本都依赖于以下几个函数(聚合函数,统计函数):
count(*
): 统计一组中的数量,通常用“*
”做参数
max(字段名):获取该字段中在该组中的最大值。
min(字段名):获取该字段中在该组中的最小值。
sum(字段名):获取该字段中在该组中的总和。
avg(字段名):获取该字段中在该组中的平均值。
两级分组示例:
having子句
having子句的含义其实跟where子句完全一样,就是进行“条件筛选”,但其只是针对分组查询(group by子句)可用的条件筛选。换句话说,如果使用having,就必须紧跟在group by后面使用。
having是对分组子句进行的条件判断,则其判断的条件都应该是“组”级别的数据,即要么对group by中的字段进行判断,要么对使用了聚合函数的字段进行判断。
示例
:
# 找出产品中的最高价大于4000的那些品牌
select pinpai from product group by pinpai having max(price) > 4000;
# 找出产品数量超过2个的品牌
select pinpai, count(pinpai) as shuliang from product group by pinpai having shuliang>2;
where是针对表的字段的值进行“条件判断”,having是只针对group by之后的“组”数据进行条件判断,
即其不能使用:字段名>10,但可以使用:count(字段名)>10, 或 max(price) > 2000, 但如果字段是分组依据,也可以。
当然,通常也可以使用select中的有效的字段别名,比如:
select count(*) as f1 , max(f1) as f2 from tab1 group by f3 having f1 > 5 and f2 < 1000;
举例:
再使用逻辑运算符:
order by子句
使用形式
:
order by 排序字段名1 [排序方式ASC|DESC], 排序字段2 [排序方式ASC|DESC] .....;
含义说明
:
对前面取得的数据(含from子句,where子句,group子句,having子句的所有结果)来指定按某个字段的大小进行排列(排序)。
可以指定第一排序字段,第二排序字段,等等。后一排序字段都是在前一排序字段值已经相同的情况下的排序。
如果指定多个字段排序(虽然不常见),则其含义是,在前一个字段排序中相同的那些数据里,再按后一字段的大小进行指定的排序。
排序只有2种方式:排序可以按升序(正序ASC)或降序(倒序DESC)进行,默认ASC,可以省略,(省略)的话就是升序。
示例
:
select * from product order by chandi;
select * from product order by chandi, price desc;
select * from product order by chandi asc, price desc;
limit子句
使用形式
:
limit [起始行号start], 要取出的行数num;
含义说明
:
表示对前面取得的数据(可能有where条件并进行了分组而且做过了排序)来限定取得其中的某部分“局部连续的若干条”数据(从第start行开始取num行)。
起始行号start:要取得的行数,如果结果集中从指定的行号开始到最后没有这么多行,则就只取到最后。
注意
:
- 数据的起始行号数start是从0开始算起的。
- 第一个起始行号为0,可以省略,则表示是从0行开始取得所指定的行数的,则为默认行号(0)。
应用场景
:
主要用于网页上常见分页需求。
分页原理:
分页的前提:人为指定每页显示的条数,$pageSize = 3;
# 显示(取得)第1页数据:
select * from 表名 limit 0, $pageSize;
# 显示(取得)第2页数据:
select * from 表名 limit 3, $pageSize;
# 显示(取得)第3页数据:
select * from 表名 limit 6, $pageSize;
# 显示(取得)第n页数据:
select * from 表名 limit (n-1)*$pageSize, $pageSize;
示例代码
: