数据库selectgroupby和having语句多表连接查询复合查询
1.SELECT --group by ⼦句
group by ⼦句按照指定的列column_name对表数据进⾏分组
group by 后⾯跟的列也叫分组特性列
使⽤group by后,能选择的列通常只能包括分组特性列和聚合函数
聚合函数
1.按照班号分组,列出学⽣表中的班号 (注意:按照班号进⾏分组,班号就不会有重复值)
select cno from stu group by cno;cno分组特性列
2.按照班号分组,列出学⽣表中的班号,还要列出学⽣姓名
select sname,cno from stu group by cno;
查询报错
注意:学⽣有20⼈,姓名⼀共20⾏记录,班号分组去重后有4⾏记录,20⾏⽆法与4⾏拼接在⼀起
使⽤group by后,能选择的列通常只能包括分组特性列和聚合函数
除⾮⽤group_concat字符串聚合函数把每个班的学⽣姓名变成字符串,每个班⼀⾏:
select cno,group_concat(sname) from stu group by cno;
3.按照班号分组,列出学⽣表中的班号,统计每个班的平均⾝⾼,平均体重,⼈数,最⾼分,不包括未分班的那些同学
select cno 班号,avg(height) 平均⾝⾼,avg(weight) 平均体重,count(*) ⼈数,max(score) 最⾼分 from stu where cno is not null group by cno;
4.先按照班号分组,再按照性别分组,列出学⽣表中的班号和性别,统计出每个班男⼥⽣的平均⾝⾼,平均体重,⼈数,最⾼分,不包括未分班的那些同学,结果先按班号,再按照男⼥s的顺序排序
select cno 班号,sex 性别,avg(height) 平均⾝⾼,avg(weight) 平均体重,count(*) ⼈数,max(score) 最⾼分 from stu where cno is not null grou p by cno,sex order by cno,sex desc;
5.按照学⽣出⽣年份分组,统计出所有学⽣每个年份的⼈数,最⾼分,最低分,按照年份排序
select year(birth) 出⽣年份,count(sno) ⼈数,max(score) 最⾼分, min(score) 最低分 from stu group by year(birth) order by 1;  +分组特性列和函数
2.SELECT - HAVING⼦句
HAVING⼦句是对group by产⽣的结果集的过滤
HAVING⼦句可以对分组特性列column_name进⾏过滤,也可以对聚合函数(aggregate_function(列))的值进⾏过滤
1.按照学⽣出⽣年份分组,统计出所有学⽣每个出⽣年份的⼈数,最⾼分,最低分,按照年份排序,并从结果中出⼈数超过2个,并且最⾼分有超过700分的年份分组
select year(birth) 出⽣年份,count(sno) ⼈数,max(score) 最⾼分, min(score) 最低分 from stu group by year(birth) having count(*)>2 and max(score)>700 order by 1;
分组特性列+分组函数  having有 where没有
2.已分班的学⽣中,哪些班学⽣的平均⾝⾼超过175,列出其班号和⼈数
select cno 班号,count(*) ⼈数 from stu where cno is not null group by cno having avg(height)>175 order by 1;
已分班的学⽣中,哪些班的学⽣每个⼈的体重都超过50公⽄,列出其班号和⼈数
select cno 班号,count(*) ⼈数 from stu where cno is not null group by cno having min(weight)>50 order by 1;
统计1班的学⽣⼈数,列出班号和⼈数
select cno 班号,count(*) ⼈数 from stu group by cno having cno=1;
或者
select 1 班号,count(*) ⼈数 from stu where cno=1;
第⼀种⽅法先使⽤group by统计,再⽤having过滤统计结果,统计了和1班不相⼲的其他班级的⼈数,浪费了系统CPU资源,效率低;第⼆种⽅法,先⽤where⼦句过滤掉了不相⼲班级的⼈员,然后直接统计1班的⼈数,效率⾼
统计⼈数超过5个的班号和⼈数,结果按照班号排序,只显⽰⼀⾏记录
select cno 班号,count(*) ⼈数 from stu where cno is not null group by cno having ⼈数>5 order by 1 limit 1;
也可以写为:
select cno 班号,count(*) ⼈数 from stu where cno is not null group by 班号 having ⼈数>5 order by 班号 limit 1;
也可以写为:
select cno 班号,count(*) ⼈数 from stu where cno is not null group by 班号 having ⼈数>5 order by 班号 limit 1;
MySQL查询语句参考执⾏步骤:
了解查询语句发到MySQLD后,服务器端的处理步骤有助于降低语句书写错误的可能性(注:不同数据库处理步骤略有不同)。
初学查询常见的错误如下:
select cno,count(*) from stu where count(*)>5;
where⼦句第⼆步执⾏,要调⽤count(*)第五步产⽣的结果,结果还没有产⽣,报错!
select cno 班号 from stu where 班号=1;
where⼦句第⼆步执⾏,调⽤⾄少第三步才能产⽣的别名,报错!
where和having的区别(以例5举例说明)
相同点:
都是对表⾏按照条件进⾏的筛选
不同点:
where对原始的stu表按照条件筛选⾏
having对分组后的新表按照条件筛选⾏
3.视图 VIEW  创建视图语法视图主要作⽤视图做DML操作
属于关系型数据库中的⼀种常⽤数据对象,保存⼀段select语句,可以把视图名称当作普通表来使⽤
创建视图语法:
CREATE VIEW vtbl_name as select_statement;
查看视图
视图主要作⽤:
1.提⾼数据安全性(隐藏部分⾏和列)
2.简化查询
可以将常⽤的查询语句写成视图的形式被其他查询调⽤,这样可以降低查询语句的复杂度,提⾼可读性
1.对视图做DML操作查看有哪些视图查看视图的定义:
视图仅仅保存SELECT语句,其select语句中的表称为基表(或母表),视图对应的数据是放在基表中的,基表中数据产⽣变化,视图的结果集也会产⽣变化。即:视图⾥⾯的数据发⽣变化,其实是基表中数据的变化所致
如果视图和其相关基表存在记录⼀⼀对应的关系,排除基表上存在约束的条件,通常可以对视图做DML操作,但是不要轻易对视图做DML操作,以防⽌对基表数据产⽣意想不到的影响
查看有哪些视图:
show table status\G
其中“comment”值为“view”的表是视图
查看视图的定义:
show create table view_name;
4.多表连接查询
将分散在多个表中的信息(列)横向合并在⼀起
通常需要指明连接条件
⼀般会根据表列的实际业务含义进⾏连接,这样才有实际意义
多表连接查询和单表查询相⽐会耗费更多的系统资源
语法
不使⽤表别名
lumn, lumn from
select语句查询日期table1 [inner|left|right] join table2
l1 = l1;
使⽤表别名
lumn from
table1 a [inner|left|right] join table2 b
l1;
分类
交叉连接