136 Mysql 语句之group by, 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

### 在 MySQL 中组合使用 GROUP BY, ORDER BYHAVING 子句 在 SQL 查询语句中,`GROUP BY`, `ORDER BY` 和 `HAVING` 是用于数据分组、排序以及条件过滤的重要子句。这些子句可以一起工作来处理复杂的数据查询需求。 #### 使用 GROUP BY 进行分组操作 当需要按照某个字段或者多个字段对记录进行分类汇总时,会用到 `GROUP BY` 子句。它通常与聚合函数(如 COUNT(), SUM() 等)配合使用以计算每组内的统计数据[^1]。 ```sql SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id; ``` 此例子展示了按部门 ID 对员工表中的工资求平均值的操作。 #### 应用 HAVING 来设置分组后的筛选条件 不同于 WHERE 子句作用于单条记录上的布尔表达式判断,HAVING 则是在完成分组之后针对整个组的结果施加约束条件。这意味着只有满足特定标准的那些组才会被返回给最终结果集[^2]。 ```sql SELECT department_id, COUNT(*) as num_employees FROM employees GROUP BY department_id HAVING COUNT(*) > 50; -- 只显示拥有超过50名成员以上的部门 ``` 这段代码表示只选取具有多于五十位雇员数量的各个部门的信息。 #### 添加 ORDER BY 实现有序排列 为了使输出更加直观易读,在获取到了所需的数据集合后还可以通过指定列来进行升序 (ASC) 或降序 (DESC) 的排序展示方式。这一步骤往往放在所有其他逻辑运算结束之后执行[^3]。 ```sql SELECT department_id, MAX(hire_date), MIN(hire_date) FROM employees WHERE hire_date IS NOT NULL GROUP BY department_id HAVING DATEDIFF(MAX(hire_date), MIN(hire_date)) >= 365 ORDER BY MAX(hire_date); -- 首先排除掉入职日期为空的情况, -- 接着统计各部门最晚和最早的雇佣时间差大于等于一年的所有情况, -- 并依据最大入职日期从小到大排序。 ``` 综上所述,合理运用这三个关键字能够帮助构建高效而精确的数据检索方案。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值