2.数据检索|模糊查询|数据排序|数据分组| 常见问题0726

时间:2022-09-10 09:42:05
 

难点====分组查询group by...having

        在分组查询中,查询的列名

        必须出现在group by后或者在聚合函数中

        --查询平均工资大于两千块钱的部门

        select department_id,avg(wages)

        from employee

        where department_id  is not null

        group by department_id

        having avg(wages)>2000

 

1. 数据检索

l       Top Distinct

l       Top 获取前几条数据

l       获得年纪最小的5个学生

l       获得年纪最大的10%的学生

l       Distinct 去除重复数据

l       select distinct sName from student

l       select distinct sName,sAge from student

l       DISTINCT是对整个结果集进行数据重复处理的,而不是针对某一个列

--Top distinct

select top 5 * from student

order by sAge

--获取前10%的学生

select top 10 percent sName,sAge

from student

 

select distinct sName from student

2.聚合函数

l       SQL聚合函数:MAX(最大值)、MIN(最小值)、AVG (平均值)、SUM (和)、COUNT(数量)

l       平均成绩select avg(english) from score

l       男学生出生日期的最大值和最小值:SELECT select max(sBirthday),min(sBirthday) from student where sSex='男'

聚合函数

        --avg() 平均值

        --sum   求和

        --count 求行数

        --min   求最小值

        --max   求最大值

select max(english)from score

select * from score

 

select sum(english)/count(*)from score

select count(*)from student where sSex='男'

 

select sName,sAge,sSex from student

where sAge between 20 and 30 and sSex='男'

带条件查询

        select 列 from 表 where 条件

        between...and...

•           select sName,sAge from student where sClassId=1 or sClassId=2 or sClassId=3

•         select sName,sAge from student where sClassId in (1,2,3)

 

带条件的查询-模糊查询

查询所有姓张的同学

Select * from student where left(sName,1)=‘张‘   看上去很美,如果改成查询名字中带亮的学生怎么做?

换一种做法 like 

l       Select  * from student where sName like ‘张%’    会吧所有姓张的都查询到,现在我想查询姓张并且名字是一个字的学生?

l       Select  * from student where sName like ‘%亮%’

通配符 %多字符匹配的通配符,它匹配任意次数(零或多个)出现的任意字符

通配符_ 单字符匹配,它匹配单个出现的字符

[] 只匹配一个字符  并且这个字符必须是[]范围内的    [0-9]  [a-z][abc]

--模糊查询

select left ('123',1)

select * from Student where left(sName,1)='张'

 

select * from Student where sName like '张%'

select * from Student where sName like '%亮%'

 

空值处理

数据库中,一个列如果没有指定值,那么值就为null,这个null和C#中的null,数据库中的null表示“不知道”,而不是表示没有。因此select null+1结果是null,因为“不知道”加1的结果还是“不知道”。

select * from score where english = null ;

select * from score where english != null ;都没有任何返回结果,因为数据库也“不知道”。

SQL中使用is null、is not null来进行空值判断: select * from score where english is null ; select * from score where english is not null ;

--null

select null+123

select * from score where english is not null

 

数据排序

ORDER BY子句位于SELECT语句的末尾,它允许指定按照一个列或者多个列进行排序,还可以指定排序方式是升序(从小到大排列,ASC)还是降序(从大到小排列,DESC)。

按照年龄升序排序所有学生信息的列表:SELECT * FROM  Student ORDER BY sAge ASC

按照英语成绩从大到小排序,如果英语成绩相同则按照数学成绩从大到小排序 :SELECT * FROM  Score ORDER BY english DESC,math DESC

ORDER BY子句要放到WHERE子句之后 : SELECT * FROM  Score where english>=60 and math>=60 ORDER BY english DESC,math DESC

--order by

select top 2 * from student

order by sAge desc

 

select * from student

order by sName desc

 

select * from score

order by english asc,math desc

 

select * from score

where english>60 and math>60

order by english desc,math asc

数据分组

l       出现聚合函数后要加group by 字句

l       select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息

l       按照班级进行分组统计各个班级的人数: select sClassId,count(sName) from student group by sClassId

l       GROUP BY子句必须放到WHERE语句的之后

l       没有出现在GROUP BY子句中的列是不能放到SELECT语句后的列名列表中的 (聚合函数中除外)

l       错误: select sClassId,count(sName),sAge from student group by sClassId(因为sAge没有出现在group by 之后)

l       正确: select sClassId,count(sName),avg(sAge) from student group by sClassId

--group by sClassId

--分组就是把sClassId相同值的那些行,合并为一行

--当有“每个”的含义的时候使用分组

 

--每个班有多少学生

select count(*),sClassId from student

group by sClassId

--第一个问题,使用group by后,select之后的列必须出现在group by字句中或者聚合函数中

select count(sId) as '个数',sClassId from student

where sSex='男'

group by sClassId

--出错,聚合函数不能出现在where字句中

select count(sId),sClassId,avg(sAge) from student

where avg(sAge)>20

group by sClassId

Having语句

Having 是Group By的条件对分组后的数据进行筛选

在Where中不能使用聚合函数,必须使用Having,Having要位于Group By之后,

查询班级人数超过三个人的班级

select sClassId,count(sName) from student group by sClassId having count(sName)>3

注意Having中不能使用未参与分组的列,Having不能替代where。作用不一样,Having是对组进行过滤。

--求平均年龄超过岁的那些班

--having对分组过后的数据进行筛选(和where的作用不同)

select count(sId),sClassId,avg(sAge)from student

group by sClassId

having avg(sAge)>20

select sClassId,count(sName) from student group by sClassId having sAge>30

//错,having是对分组后信息的过滤,能用的列和select中能用的列是一样。

//having无法代替where。

--求人数超过人的班

select count(sId),sClassId from student

group by sClassId

having count(sId)>5

--分组练习

--求男生和女生分别有多少人

select count(sId),sSex from student

group by sSex

 

--求每个班有多少男生

select count(sId),sClassId from student

where sSex='男'

group by sClassId

 

--求平均年龄小于的那些班

select count(sId),sClassId,avg(sAge)from student

group by sClassId

having avg(sAge)<22

 

以上都是要掌握的,下面是要了解的

l       联合结果集

简单的结果集联合:

select tName,tSex from teacher union

select sName,sSex from student

基本的原则:每个结果集必须有相同的列数;每个结果集的列必须类型相容。

select tName,tSex,-1 from teacher union

select sName,sSex,sClassId from student

 

    8、同时插入多条语句

        把查询到的结果插入到现有表中

            insert into 现有表

            select 字段

            from 表

        把现有表的数据插入到一个新表 

            select 字段

            into 新表

            from 表

        --把现有表的数据插入到新表(表不能存在)

        --select * into newStudent from student

        --把现有表的数据复制到一个已存在的表

        --insert into backupStudent select * from students

       

    9、合并查询union 去除重复项

        union all 不去除重复项 所以效率高

        一次插入多条数据

        insert into Score(studentId,english,math)

        select 1,80,100 union

        select 2,60,80

l       Union all

•         select tName,tSex from teacher union

•         select sName,sSex from student

UNION合并两个查询结果集,并且将其中完全重复的数据行合并为一条

•         select tName,tSex from teacher union all

•         select sName,sSex from student

Union因为要进行重复值扫描,所以效率低,因此如果不是确定要合并重复行,那么就用UNION ALL

 

--union

--列的个数一致,类型一致

--排序去除重复数据

select tName,tSex,-1 from teacher union

select sName,sSex,sClassId from student

--union all

--直接连接两个结果集

select tName,tSex from teacher union all

select sName,sSex from student

--要求在一个表格中查询出学生的英语最高成绩、最低成绩、平均成绩

select '最高成绩',max(english) from score union all

select '最低成绩',min(english) from score union all

select '平均成绩',avg(english) from score

 

 

--查询每位老师的信息,包括姓名、工资,并且在最后加上平均工资和最高工资

select tName,tSalary from teacher union all

select '平均工资',avg(tSalary) from teacher union all

select '最高工资',max(tSalary) from teacher

 

--一次插入多条数据

insert into Score(studentId,english,math)

select 1,80,100 union

select 2,60,80 union

select 3,50,59 union

select 4,66,89 union

select 5,59,100

 

select * from score

 

--把现有表中的数据插入到新表中(newStudent表不能存在)

--去除表中重复数据

select * into newStudent from student

select * from newStudent

 

--把现有表的数据复制到一个已存在的表

truncate table newStudent

insert into newStudent select sName, sAge, sNo, sBirthday, sClassId, sSex, sIntime, sPhone from student