count,sum,max,avg 和 group by,order by,having where ,on ,union ,join 基础

聚合函数

在介绍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语句的后面,作为分组的依据;要么就要被包含在聚合函数中(即要保证,归组时,每组中的元素值是唯一的。一组值对应一个计数值,不能有两个计数值)

扫描二维码关注公众号,回复: 3575625 查看本文章

为什么呢,根据前面的说明:DepartmentID相等的数据归为一组,只显示一条记录,那如果数据集中有这样三条数据。

      DepartmentID                              DepartmentName

            dept001                                            技术部

            dept001                                            综合部

            dept001                                            人力部

那我只能显示一条记录,我显示哪个?没法判断了。到这里有三种选择:

  1. 把DepartmentName也加入到分组的条件里去(GROUP BY DepartmentID,DepartmentName),那这三条记录就是三个分组。
  2. 不显示DepartmentName字段。
  3. 用聚合函数把这三条记录整合成一条记录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 会读取右边数据表的全部数据,即便左边表无对应数据。

所以版权归原博客博主所有,但在引用过程中没有标明引用出处,若对原博主版权构成侵犯或由意见,请及时联系。

猜你喜欢

转载自blog.csdn.net/abbcccdde/article/details/82983975
今日推荐