聚合函数
在介绍GROUP BY 和 HAVING 子句前,我们必需先讲讲sql语言中一种特殊的函数:聚合函数, 例如SUM, COUNT, MAX, AVG等。这些函数和其它函数的根本区别就是它们一般作用在多条记录上。
SELECT SUM(population) FROM bbc
这里的SUM作用在所有返回记录的population字段上,结果就是该查询只返回一个结果,即国家的总人口数。
GROUP BY用法
Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”。它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理。
注意:group by 是先排序后分组;
举例子说明:如果要用到group by 一般用到的就是“每这个字段” 例如说明现在有一个这样的表:每个部门有多少人 就要用到分组的技术
select DepartmentID as '部门名称', COUNT(*) as '个数' from BasicDepartment group by DepartmentID
这个就是使用了group by +字段进行了分组,其中我们就可以理解为我们按照了部门的名称ID,DepartmentID将数据集进行了分组;然后再进行各个组的统计数据分别有多少;
通俗一点说:group by 字段1,字段2。。。(整个表中不止这两个字段)表示数据集中字段1相等,字段2也相等的数据归为一组,只显示一条数据。那么你可以对字段3进行统计(求和,求平均值等)
注意
select DepartmentID,DepartmentName from BasicDepartment group by DepartmentID
–-将会出现错误
自我总结:因为DepartmentID可能对应多个DepartmentName,所以在归为一组的时候,不知道怎么归分,所以错误。
选择列表中的列 ‘DepartmentName’ 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。这就是我们需要注意的一点,如果在返回集字段中,这些字段要么就要包含在Group By语句的后面,作为分组的依据;要么就要被包含在聚合函数中(即要保证,归组时,每组中的元素值是唯一的。一组值对应一个计数值,不能有两个计数值)。
为什么呢,根据前面的说明:DepartmentID相等的数据归为一组,只显示一条记录,那如果数据集中有这样三条数据。
DepartmentID DepartmentName
dept001 技术部
dept001 综合部
dept001 人力部
那我只能显示一条记录,我显示哪个?没法判断了。到这里有三种选择:
- 把DepartmentName也加入到分组的条件里去(GROUP BY DepartmentID,DepartmentName),那这三条记录就是三个分组。
- 不显示DepartmentName字段。
- 用聚合函数把这三条记录整合成一条记录count(DepartmentName)
WHERE和 HAVING
HAVING子句可以让我们筛选成组后的各组数据。HAVING子句可以使用聚合函数
WHERE子句在聚合前先筛选记录.也就是说作用在GROUP BY 子句和HAVING子句前. WHERE字句中不能使用聚合函数(where后面不能出现计算的过程,根据现有值进行帅选,不进行计算)。
举例说明:
一、显示每个地区的总人口数和总面积.
SELECT region, SUM(population), SUM(area) FROM bbc GROUP BY region
先以region把返回记录分成多个组,这就是GROUP BY的字面含义。分完组后,然后用聚合函数对每组中的不同字段(一或多条记录)作运算。
二、 显示每个地区的总人口数和总面积.仅显示那些面积超过1000000的地区。
SELECT region, SUM(population), SUM(area) FROM bbc8 F4 GROUP BY region HAVING SUM(area)>1000000
在这里,我们不能用where来筛选超过1000000的地区,因为表中不存在这样一条记录。相反,HAVING子句可以让我们筛选成组后的各组数据。
需要注意说明:当同时含有where子句、group by 子句 、having子句及聚集函数时,执行顺序如下:
1、执行where子句查找符合条件的数据;
2、使用group by 子句对数据进行分组;
3、使用order by 字句进行排序;
4、最后用having 子句去掉不符合条件的组;
5、使用limit进行选取范围限制。
having子句和where子句都可以用来设定限制条件以使查询结果满足一定的条件限制。
having子句限制的是组,而不是行。where子句中不能使用聚集函数,而having子句中可以。
5种字句有严格的顺序 ,where,group by,having , order by ,limit。
即如果存在同时存在where,group by ,having,order by ,limit 出现顺序一定是where --> group by --> group by --> having -->order by --> limit.
SQL SELECT 语句 (DML语言)
select * from user where 1;--取出所有的值。等价于select from user;
select name from user where 1;--取出所有的那么值,//取出某两列,叫做投影
select age+1 from user where 1;--
select price - value from user;--投影运算,运算是广义投影。
#like 模糊匹配。
select name from user where name like 'wmh%'; -- 查找以'wmh'开头的name,%通配任意字符
select name from user where name like 'wmh___'; -- '_'下划线通配单一字符
select floor(age/10)*10 from user; --
update user set age=floor(age/10)*10 where 1; --全部更新
update user set age=floor(age/10)*10 where age between 20 and 39 ; --更新一部分
create table tmp (id int,name varchar(20)) charset utf8 engine myisam; -- 编码是utf8, 存储方案是myisam
select * from tmp where name is not null; --
group分组统计
select avg(age) from user; -- max(),min(),sum(),avg();
select count(*) from user;
select sum(age) from user;
select sum(num*age) from user;
select sum(num*age) from user group by uid;
select count(*) from user group by uid;
select cat_id,max(age) from user group by uid;
having筛选
having是在查询的基础之上进行筛选。
select age,name,(age-uid)as sub from user where 1 having sub > 20;
select name,avg(score) from result where score < 60 group by name;
select name,count(score<60) as gk, avg(score) from result group by name having gk >= 2;
select name,avg(score) as pj from user group by name;
例子:统计挂科数大于等于2门的学生name,挂科数,和平均分
select name,sum(score<60) as gk, avg(score> as pj
from user group by name
having gk >=2;
order by 排序
降序: desc
升序: asc (默认)
select * from user order by age;
select * from user order by age desc, uid asc, name desc;
limit 限制条目数量
对结果集的结果进行限制(有选择性的拿出其中的几条)
在分页的时候发挥作用。
两个参数:一个是跳过多少行(偏移量),和取出数量
select * from user order by age desc, uid asc, name desc limit 2,3;
select *from user order by age desc limit 0,1;
字句的查询陷阱
5种字句有严格的顺序 ,where,group by,having , order by ,limit
where 子查询;
内层查询结果,作为外层比较的条件。
select * from user order by age limit 0,1;//查询最大年龄
select * from user age = 32;//
select max(age) from user;
select * from user where age=(select max(age) from user); -- where型子查询。
select uid,max(age) from user group by uid; --输出uid下年龄最大的值
select * from user where age in(select max(age) from user group by uid); --
from子查询:
select * from user where age in(select max(age) from user group by uid); --(都是闭区间),与之对应的是not in
select name from from(select * from user where 1 order by age desc) as tmp group by uid;
exists子查询:
select * from category where exists (select * from goods where goods. cat_id = category.cat_id);
新手的1+N模式查询:
一条语句--->N条数据--->N 条查询
连接查询
内连接(交集)
select boy.hid boy.bname,gril.hid girl.game from boy inner join girl on boy.hid = girl.hid;
select * from table1 inner join table2 on table1.xx = table2.xx; --匹配查询
左连接:
select * from table1 left join table2 on table1.xx = table2.xx; --以左表为准查询,差不到的补null
右连接:
select * from table1 right join table2 on table1.xx = table2.xx; --以左表为准查询,差不到的补null
并集:
\c退出mysql 命令
select m.* , t.name as hteam , t2.tname as gteam
from
m inner join t as t1 on m.hid= t1.tid inner join t as t2 on m.hid = t2.tid;
select mid,t1.tname as hname ,mres,t2.tname as gteam, matime
from
m inner join t as t1 on m.hid = t1.hid inner join t as t2 on m.gid = t2.tid
where matime between '2006-08-1' and '2008-08-08';
union查询:
必要条件:各语句取出的列数必须相同。
sql1 N 行
sql2 M 行
sql1 union sql2 , M+N行(可能小于M+ N )
select * from a union select * from b;
注意:使用union 时,完全相等行,将会被合并,我们一般不让union 进行合并。使用union all 可以避免合并。
select * from a union all select * from b;
讨论:union 字句中,不用谢order by (写了也没效果,sql合并后得到的总的结果,可以order by ,字句的order by失去意义。)
uinion 面试题:
求两张表中相同名字的num相加:
select * from a union all select * from b ;
select id sum(num) from (select * from a union all select * from b ) as tmp group by id;
sql中inner join和natural join的区别
inner join是内连接,显示符合连接条件的记录
语法如下:
select select_list from table1 inner join tabl2 on table1.column1=table2.column1
natural join是对两张表中字段名和数据类型都相同的字段进行等值连接,并返回符合条件的结果 。
natural join是自然连接,自动对两个表按照同名的列进行内连接语法如下:
select select_list from table1 natural join tabl2
使用自然连接要注意,两个表同名的列不能超过1个。
natural join:指明了两表进行自然连接,并且连接是基于两表中所有同名字段的。
join...using:用于两表有同名字段但数据类型不同,或者使用多个同名字段中的某一个做等值连接
join...on :最为灵活,可以指明连接的条件。
新加入字段导致自然连接的条件发生变化,修改后变为了指定字段的等值连接。像这种项目中的类似问题,还是不要使用自然连接的好,最开始就使用join...using或join...on避免他人因修改表结构造成的错误。
on与where有什么区别
注意on与where有什么区别,两个表连接时用on,在使用left jion时,on和where条件的区别如下:
1、 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据。
所以版权归原博客博主所有,但在引用过程中没有标明引用出处,若对原博主版权构成侵犯或由意见,请及时联系。