mysql select查询的5个子句

where、group by、having、order by、limit是select查询中的5个子句,理解了这5个子句的执行过程,才能算是真正的对mysql select查询入门了。
它的执行过程是这样的:( 如果同时出现在一条select中,必须按以下顺序
第一步:先是where,得到一张表。注意,where是对表进行操作得到一个临时结果;
第二步:再到5个统计函数和group by运算,得到一个结果集
(它的列名,可与原来相同,也可以不同,配合聚合函数使用,如果不使用聚合函数,就没有使用group by的必要了);
第三步:执行having。注意,having是对结果集进行操作
(一般是对group by处理后的结果进行限制,也就是使用聚合函数后的结果进行排除,如果不使用group by,就没有使用having的必要,
   因为having能做的事,where都能做,效率高很多;HAVING子句是配合GROUP BY使用的,单独使用HAVING本身是不符合规范的);
第四步:执行order by
第五步:执行limit。
其它重要三个知识点:
(1)列/字段相当于变量,即可以进行各种运算;
(2)where后面为表达式,为真则执行;
(3)结果集在结构上仍然是一个表,可以进行再次的查询。

一般来说,HAVING子句是配合GROUP BY使用的,单独使用HAVING本身是不符合规范的,
但是MySQL会做一个重写,加上一个GROUP BY NULL,”SELECT * FROM t HAVING id=MIN(id)”会被重写为”SELECT * FROM t GROUP BY NULL HAVING id=MIN(id)”,这样语法就符合规范了;
但是,这个 GROUP BY NULL 会产生什么结果呢?经过查看代码和试验,可以证明,GROUP BY NULL 等价于 LIMIT 1

----------------------创建表----------------------------------------
先创建一张学生成绩表
create table student(
name varchar(10) not null default '',
subject char(2) not null default '',
score tinyint not null default 0
)engine myisam charset utf8;
再插入一些数据
insert into student values('张三','语文',80),('张三','政治',38),('张三','数学',20),('李四','英语',52),('李四','化学',47),('王五','语文',70),('王五','物理',58),('陈六','数学',38);

-------------------------select查询的执行过程------------------------
题目要求:查询各个学生成绩不及格课程的平均分
mysql> select name,avg(score) from student where score<60 group by name;
+------+------------+
| name | avg(score) |
+------+------------+
| 张三 |    29.0000 |
| 李四 |    49.5000 |
| 王五 |    58.0000 |
| 陈六 |    38.0000 |
+------+------------+
4 rows in set (0.00 sec)
过程解析:
第一步:执行where条件,但是并没有选择列,结果得到一张表,它的列与原始列相同,并且满足where条件。即执行下边这条语句
mysql> select * from student where score<60;
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 政治    |    38 |
| 张三 | 数学    |    20 |
| 李四 | 英语    |    52 |
| 李四 | 化学    |    47 |
| 王五 | 物理    |    58 |
| 陈六 | 数学    |    38 |
+------+---------+-------+
6 rows in set (0.00 sec)
第二步,进行max/min/sum/avg/count统计运算,以及group by运算。它得到的是一个结果集,即我们的最终答案。
mysql> select name,avg(score) from student where score<60 group by name;
题目要求:查询出有2门及2门以上课程不及格的学生的平均成绩。(即,该学生有2门及2门以上课程不及格;查询的是满足条件的学生,所有课程的平均分)

采用逆向思维:先查询各个学生的平均分,再筛选出挂课2门及以上的学生;
如果采用正向思维:先查找出挂科2门及以上的学生,再获取平均分。语句很复杂
------------------------------------------------------------------------------------
逆向思维正确语句为:
mysql> select name,avg(score),sum(score<60) as gk from student group by name having gk>=2;
+------+------------+------+
| name | avg(score) | gk   |
+------+------------+------+
| 张三 |    46.0000 |    2 |
| 李四 |    49.5000 |    2 |
+------+------------+------+
2 rows in set (0.07 sec)
-------------------------------------------------------------------------------------
第一步:查询各个学生的平均成绩。注意,这里多添加了一个字段,不及格标记为1,及格标记为0。这是利用了列即是变量的特点,进行运算。
第二步:having gk>=2,筛选先挂科数目大于等于2的学生。


补充:

1.where :

where后跟条件用来筛选我们所需的行。它后面可以跟的操作符有=、!=、<、>、<=、>=、 in、 like(可以和通配符%结合一起用,效果将会更好) 、between....and........ AND、OR 、NOT 

如:select id,name,score form student where score in (每组里面的最高分组合); 

2.group by

GROUP BY 语句用于结合合计函数(也叫聚合函数sum count avg max min),根据一个或多个列对结果集进行分组。否则没有多大的意义

    group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面
    如:我们对文字的分类id进行分组,查询每组分类的文章数 select articlecategory_id,count(*) from article group by articlecategory_id;
再次提示:
如果你使用了group by,而没有相应的使用聚合函数那么结果就没有意义了,按照实际情况来思考的话就变成了一对多了(也就是一个分组对应多个对象(也就是多行),那么一个分组对应多行数据的显示就变成了分组和第一行数据进行显示了,所以此时我们应该使用聚合函数(聚合函数就是把多个变成一),也就是对多行数据进行筛选,得到我们想要的数据,如:可以使用count计算论坛小组总帖子数,可以使用sum来计算<pre id="best-answer-content" class="reply-text mb10" name="code" style="word-wrap: break-word; margin-top: 0px; margin-bottom: 10px; padding: 0px; zoom: 1;">论坛小组帖子总回复数,可以使用max来计算论坛小组最多回复的帖子,可以使用min来计算论坛小组最少回复数(没有多大意义,商城最便宜的商品就意义了),可以使用avg来计算论坛每周的平均访问量(商城所有商品的平均价格)等。<pre id="best-answer-content" class="reply-text mb10" name="code" style="word-wrap: break-word; margin-top: 0px; margin-bottom: 10px; padding: 0px; zoom: 1;">
 
 
 
 

3.having 

这个是针对查询的结果进行作用,只能对结果拥有的列进行操作,与where不同的是where是针对原表(就是from后面的那张表的字段)发挥作用。其中having里面可以使用 聚合函数。为group by子句设置条件,类似于where为select语句设置条件的方法。having的查找条件可以包括集合函数表达式。除此之外,它的查找条件与where查找条 件相同。

select articlecategory_id,count(*) from article group by articlecategory_id having count(*)<5;

4.order by 排序 

可以针对字段进行排序,order by 字段1 [asc] 升序,[desc] 降序

5.limit 获取条目的限定

语法 limit offset,N

总结:where是针对from后面跟的表进行处理,而group by having order by limit则是针对select后面的字段进行处理。从它们的结构角度来看则:先整体后部分。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值