136 Mysql 语句之group by, having, count

本文深入探讨了Mysql中的groupby、having和count等聚合函数的使用技巧,通过多个实例展示了如何进行数据分组、筛选和统计,包括跨表联接、成绩统计、条件过滤等场景。

Mysql的group by, having, count

平时经常用错,这里举一些使用的例子。

  • group by
  • having
  • 聚合函数count,avg,min,max,sum等

一些基础的sql语句:
http://www.cnblogs.com/xinge1993/p/4769468.html

常用的sql
http://www.cnblogs.com/sunada2005/p/3411873.html


group by

根据by后面的字段的值分组,值相同的归为一组。

having

group by后,进行组类的判断。where后面也是跟条件判断,但是where是group by之前(如果有group by的话),针对每一行数据;having是针对group by后的组级别的数据。

count等聚合函数

  • count统计条数;
  • sum求和;
  • avg求平均;
  • max最大;
  • min最小。

注意:聚合函数并不只和group by一起用,不是只有group by的地方才能用它。
比如: select count(*) from stu; # 统计stu表的条数

示例

1:group、两个表join

create table tmp(rq varchar(10),shengfu nchar(1))

insert into tmp values('2005-05-09','胜')
insert into tmp values('2005-05-09','胜')
insert into tmp values('2005-05-09','负')
insert into tmp values('2005-05-09','负')
insert into tmp values('2005-05-10','胜')
insert into tmp values('2005-05-10','负')
insert into tmp values('2005-05-10','负')

统计:每一天的胜负次数。输出是:rq,胜次数,负次数。

select a.rq, a.sheng, b.fu from (select rq, count(shengfu) sheng from tmp where shengfu='胜' group by rq, shengfu) a
join
(select rq, count(shengfu) fu from tmp where shengfu='负' group by rq, shengfu) b
on a.rq = b.rq

结果截图

2:每个学生的成绩在90分以上的各有多少门

create table sc (
sno int,
pno varchar(16),
grade int
)

insert into sc values(1, 'YW', 95)
insert into sc values(1, 'SX', 98)
insert into sc values(1, 'YY', 90)
insert into sc values(2, 'YW', 89)
insert into sc values(2, 'SX', 91)
insert into sc values(2, 'YY', 92)
insert into sc values(3, 'YW', 85)
insert into sc values(3, 'SX', 88)
insert into sc values(3, 'YY', 96)
insert into sc values(4, 'YW', 95)
insert into sc values(4, 'SX', 89)
insert into sc values(4, 'YY', 88)

select sno, count(*) from sc where grade>=90 group by sno;

# 刚开始写成这样下面这样,是错误的:
select sno, count(*) from sc group by sno, grade having grade>=90

输出结果:

输出

3:至少有两门课程在90分以上才能有资格,列出有资格的学生号及90分以上的课程数

select sno,count(*) from sc where grade>=90 group by sno having count(*)>=2
  •  

输出

4:列出平均成绩大于等于90分并且语文课大于等于95的学生sno和平均成绩

select sno, avg(grade) from sc where sno in (select sno from sc where grade>=95 and pno='YW') group by sno having avg(grade)>=90

# 两种错误的,错误在哪自己分析
select sno from (select * from sc where pno='YW' and grade>=95) group by sno having avg(grade)>=90

select sno, grade from sc where sno in (select sno from sc group by sno having avg(grade)>=90) and pno='YW' and grade>=95 group by sno

输出

5 :平均成绩至少比学号是3的平均成绩高的学生学号以及平均分数

# 两种方法
select sno, avg(grade) from sc group by sno having avg(grade) > (select avg(grade) from sc where sno=3 group by sno)

select sno, avg(grade) from sc group by sno having avg(grade) > (select avg(grade) from sc where sno=3)
#上面这句,having后面的select子查询,用到了聚合函数avg但是没有group by。看出,group by和聚合函数不是天生在一起用的。

输出

6 : 查询每一个班级中年龄大于20且性别为男的人数

这个题来自http://www.cnblogs.com/wang-123/archive/2012/01/05/2312676.html 的最后面。但是,原博客中的sql语句是错误的。

create TABLE Table1
(
    ID int auto_increment primary key,   
    classid int, 
    sex varchar(10),
    age int
) 

insert into Table1(classid, sex, age) values(1,'m',20)
insert into Table1(classid, sex, age) values(2,'f',22)
insert into Table1(classid, sex, age) values(3,'m',23)
insert into Table1(classid, sex, age) values(4,'m',22)
insert into Table1(classid, sex, age) values(1,'m',24)
insert into Table1(classid, sex, age) values(2,'f',19)
insert into Table1(classid, sex, age) values(4,'m',26)
insert into Table1(classid, sex, age) values(1,'m',24)
insert into Table1(classid, sex, age) values(1,'m',20)
insert into Table1(classid, sex, age) values(2,'f',22)
insert into Table1(classid, sex, age) values(3,'m',23)
insert into Table1(classid, sex, age) values(4,'m',22)
insert into Table1(classid, sex, age) values(1,'m',24)
insert into Table1(classid, sex, age) values(2,'f',19)

select COUNT(*) as '>20岁人数', classid from Table1 where sex='m' and age>20 group by classid

# 原博客错误的sql
select COUNT(*) as '>20岁人数', classid from Table1 where sex='m' group by classid,age having age>20 

输出

7 : 班级人数大于等于3人的那些班级的学生

create table stu_class_info(
    sid int,
    class_id int,
    snane varchar(32)
)

insert into stu_class_info values(1, 1, 'zhangsan')
insert into stu_class_info values(2, 1, 'zhangsan')
insert into stu_class_info values(3, 2, 'zhangsan')
insert into stu_class_info values(4, 3, 'zhangsan')
insert into stu_class_info values(5, 2, 'zhangsan')
insert into stu_class_info values(6, 2, 'zhangsan')
insert into stu_class_info values(7, 2, 'zhangsan')
insert into stu_class_info values(8, 4, 'zhangsan')
insert into stu_class_info values(9, 4, 'zhangsan')
insert into stu_class_info values(10, 2, 'zhangsan')

# 班级人数大于等于3人的那些班级的学生
select * from stu_class_info where class_id in (select class_id from stu_class_info group by class_id having count(class_id)>=3) order by class_id

输出

参考链接

http://www.cnblogs.com/xinge1993/p/4769468.html
http://www.cnblogs.com/sunada2005/p/3411873.html
http://blog.youkuaiyun.com/ooooooobh/article/details/52795073

### MySQLHAVINGGROUP BY 的区别及使用场景 #### 1. 定义与功能 `GROUP BY` 是 SQL 查询中的一个重要子句,用于将数据按照一个或多个列进行分组[^2]。通过 `GROUP BY`,可以对每组数据执行聚合操作(如求和、计数等),从而生成汇总结果。 相比之下,`HAVING` 则是对已经完成分组后的结果进一步筛选的条件语句[^3]。它类似于 `WHERE` 子句的作用,但专门应用于分组之后的数据集上。 --- #### 2. 执行顺序 在 SQL 查询中,各子句的逻辑执行顺序决定了它们的功能差异。以下是标准的执行流程: - **WHERE**: 首先过滤原始表中的记录。 - **GROUP BY**: 对经过 WHERE 过滤后的数据进行分组。 - **HAVING**: 在分组完成后,基于聚合函数的结果施加额外的过滤条件。 - **SELECT**: 提取最终所需的字段并计算表达式的值。 - **DISTINCT**: 如果存在,则去除重复行。 - **ORDER BY**: 最后一步,对结果集排序。 因此,在这个过程中,`HAVING` 只能访问由 `GROUP BY` 创建的分组级数据及其对应的聚合值[^1]。 --- #### 3. 使用场景比较 | 特性 | `GROUP BY` | `HAVING` | |-------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| | **主要用途** | 将数据划分为若干个逻辑上的组,通常配合聚合函数一起使用 | 筛选满足特定条件的分组 | | **适用范围** | 数据源层面的操作 | 聚合结果层面的操作 | | **能否独立运行** | 单独作为查询的一部分 | 必须依赖于 `GROUP BY` 或其他产生分组结构的部分 | 例如,下面是一个典型的例子: ```sql -- 统计各部门员工数量大于5的情况 SELECT department, COUNT(employee_id) AS total_employees FROM employees GROUP BY department HAVING COUNT(employee_id) > 5; ``` 上述代码展示了如何利用 `GROUP BY` 来创建部门级别的分组,并借助 `HAVING` 排除那些不达标的分组。 --- #### 4. 实际应用案例分析 假设有一个名为 `sales` 的销售记录表,其中包含以下字段:`region` (地区), `amount` (销售额),我们希望找出总销售额超过一定阈值的所有区域。 ##### 示例一:简单分组统计 如果只需要查看每个地区的总销售额而无需任何附加约束,那么仅需用到 `GROUP BY`: ```sql SELECT region, SUM(amount) AS total_sales FROM sales GROUP BY region; ``` 此处并未涉及 `HAVING` ,因为尚未引入针对分组结果的限制条件。 ##### 示例二:带条件的分组筛选 当需要限定只显示某些高绩效区域时,就需要加入 `HAVING` : ```sql SELECT region, SUM(amount) AS total_sales FROM sales GROUP BY region HAVING SUM(amount) >= 10000; ``` 此脚本不仅完成了按区划分的任务,还剔除了不符合最低收入标准的条目。 --- #### 5. 总结 综上所述,虽然两者都服务于数据分析目的,但是其侧重点各有不同——前者负责构建基础框架;后者则承担精细化调整的角色。理解两者的协作机制对于编写高效且精准的SQL语句至关重要。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值