Mysql查操作(下)

mysql查操作(下)

-- 19. 查询学生选课的所有日期(去重)
-- distinct 去重
select distinct sel_date as 选课日期
from records;

-- 查询学生选课的所有日期(去重)并排序
select distinct sel_date
from records
order by sel_date asc;
-- 20. 查询学生的籍贯(空值处理和去重)
select distinct stu_addr as 学生籍贯
from students
where stu_addr is not null and trim(stu_addr) <> '';
-- 21. 查询男学生的姓名和生日按年龄从大到小排列(排序)
select stu_name as 姓名
	,stu_birth as 生日
from students
where stu_sex = 1
order by stu_birth asc;

-- 如果生日相同那么可以按照降序排列 
select stu_name as 姓名
	,stu_birth as 生日
from students
where stu_sex = 1
order by stu_birth asc,stu_id desc;

-- 22. 将上面查询中的生日换算成年龄(日期函数、数值函数)

-- 查询时间日期select now();
-- 查询当前的时间select curtime();
-- 查询当前的日期 select curdate();
-- 查询时间戳 select current_timestamp;
-- 查看两个日期相差多少天 datediff()
-- timestampdiff 指定单位,看两个相差多少年多少天
select stu_birth as 生日
	,floor(datediff(curdate(),stu_birth)/365) as 年龄
from students
where stu_sex = 1
order by stu_birth;

-- 法二  timestampdiff 指定单位,看两个相差多少年多少天
select stu_name 
	,timestampdiff(year,stu_birth,curdate()) as 年龄
from students
where stu_sex = 1
order by stu_birth desc;

-- 23. 查询年龄最大的学生的出生日期(聚合函数)也就是出生日期值最小的 
-- 归约 reduce / 聚合 aggregate
-- python中filter数据过滤函数 
-- 规约通俗一点就是数据减少
select min(stu_birth)
	from students ;


-- 24. 查询年龄最小的学生的出生日期(聚合函数)出生日期值最大 
select max(stu_birth)
	from students;
-- 25. 查询编号为1111的课程考试成绩的最高分(聚合函数)
select max(score)
from records
where cou_id = 1111;
-- 26. 查询学号为1001的学生考试成绩的最低分(聚合函数)
-- 聚合函数遇到哦空值会跳过 
select min(score)
from records
where stu_id = 1001;
-- 27. 查询学号为1001的学生考试成绩的平均分和标准差(聚合函数) 
select avg(score) as 平均分
	,stddev_pop(score) as 标准差
    ,var_pop(score) as 方差
from records
where stu_id = 1001;
-- 28. 查询学号为1001的学生考试成绩的平均分,如果有null值,null值算0分(聚合函数)
-- ifnull(条件1,条件2) 如果是空值就返回条件2,如果不是空值就返回条件1
select avg(ifnull(score,0)) as 平均分
	from records
where stu_id = 1001;

-- coalesce 是空返回第一个值 
select avg(coalesce(score,0)) as 平均分
	from records
where stu_id = 1001;

-- 求和没算空值,但是除以是除的行数,这样空值也算进去了
select sum(score)/ count(*) as 平均分
	from records
where stu_id = 1001;

-- 29. 查询男女学生的人数(分组和聚合函数)
select case stu_sex when 1 then '男' when 0 then '女' else '总计' end  as 性别
	,count(*) as 人数
from students
group by stu_sex
with rollup;
-- 30. 查询每个学院学生人数(分组和聚合函数)
-- with rollup 总计操作 
select col_id
	,count(*) as 人数
from students
group by col_id
with rollup;
-- 31. 查询每个学院男女学生人数(分组和聚合函数)
select col_id
	,case stu_sex when 1 then '男' else '女' end  as 性别
    ,count(*) as 人数
from students
group by col_id,stu_sex
with rollup;

-- 32. 查询选课学生的学号和平均成绩(分组和聚合函数)
-- round 四舍五入
-- floor向下取整
select stu_id
	,round(avg(score),1)
 from records
 group by stu_id;
    
-- 33. 查询平均成绩大于等于90分的学生的学号和平均成绩(分组和聚合函数)

-- 分组之后还需要数据筛选的时候就不能用where了,只能使用having子句了,且放在group by的后面。 
-- 分组之前的数据筛选用where且放在group by之前,分组之后的数据筛选用having且放在group by 后面
select stu_id as 学号
	,round(avg(score),1) as 平均分
    from records
    group by stu_id
     having avg(score) >= 90;

-- 34. 查询所有课程成绩大于80分的同学的学号和姓名(分组和聚合函数)
select stu_id as 学号
    from records
    group by stu_id
having min(score) > 80;
    
-- 35. 查询年龄最大的学生的姓名(嵌套查询)
-- @是给变量赋值,前面必须写上set
set @min_birth = (select min(stu_birth) from students);
select @min_birth;
select stu_name as 名字
from students
where stu_birth = @min_birth;

-- 海象运算符 
select @min_birth := (select min(stu_birth) from students);
select @min_birth;
select stu_name
from students
where stu_birth = @min_birth;

-- 嵌套查询: 把一个查询的结果作为另外一个查询的一部分来使用,也称子查询 。
select stu_name
	from students
where stu_birth = (select min(stu_birth)
							from students);
-- 36. 查询选了两门以上的课程的学生姓名(嵌套查询/分组/数据筛选)
--
--

set @sname = (select stu_id 
						from records 
                        group by stu_id 
                        having count(*) > 2);
select @sname;
select stu_name
from students
where stu_id in (@sname);

-- 用学生id来分组 
select stu_name
	from students
    where stu_id in (select stu_id 
						from records 
                        group by stu_id 
                        having count(*) > 2) ;
-- 用=any运算符
-- all运算符 前面的字段和后面所有的字段都相等 
select stu_name
	from students
    where stu_id = any(select stu_id 
						from records 
                        group by stu_id 
                        having count(*) > 2) ;
                        
-- 37. 查询学生的姓名、生日和所在学院名称(连接查询)
-- 笛卡尔积——交叉连接 
-- 在笛卡尔积后面做一个数据筛选 
select stu_name as 姓名
	,stu_birth as 生日
    ,col_name as 学院
from students,colleges
-- 上面是笛卡尔积 
where students.col_id = colleges.col_id;

-- cross join交叉连接
select stu_name as 姓名
	,stu_birth as 生日
    ,col_name as 学院
from students cross join colleges
where students.col_id = colleges.col_id;

-- inner join 内连接 on
select stu_name as 姓名
	,stu_birth as 生日
    ,col_name as 学院
from students inner join colleges
on students.col_id = colleges.col_id;

-- natural join 自然连接,前提条件表之间必须有同名列,否则依然是笛卡尔积
select stu_name as 姓名
	,stu_birth as 生日
    ,col_name as 学院
from students natural join colleges;

-- 38. 查询学生姓名、课程名称以及成绩(连接查询)
-- 自然连接 natural join 
select stu_name as 姓名
	,cou_name as 课程
	,score as 分数
from students natural join records natural join courses
where score is not null;

-- inner join 内连接 on
select stu_name
	,cou_name
	,score
from students inner join records 
			  inner join courses
    on courses.cou_id = records.cou_id
   and students.stu_id = records.stu_id
where score is not null;

-- 普遍写法 
select stu_name
	,cou_name
	,score
from students , courses, records 
	where students.stu_id = records.stu_id
    and courses.cou_id = records.cou_id
	and score is not null;

-- 39. 上面的查询结果按课程和成绩排序取前5条数据(分页查询)
-- 除了自然连接 就需要说明是哪个表的 records.cou_id
-- 自然连接是将同名列合为一个列 
select stu_name as 姓名
	,cou_name as 课程
	,score as 分数
from students natural join records natural join courses
where score is not null
order by cou_id asc,score desc
limit 5;

-- 40. 上面的查询结果按课程和成绩排序取第6-10条数据(分页查询)
-- offset跳过多少行查询 offset 5 跳过第5页查询 
-- offset是mysql方言 
select stu_name as 姓名
	,cou_name as 课程
	,score as 分数
from students natural join records natural join courses
where score is not null
order by cou_id asc,score desc
limit 5
offset 5;

-- 41. 上面的查询结果按课程和成绩排序取第11-15条数据(分页查询)
select stu_name as 姓名
	,cou_name as 课程
	,score as 分数
from students natural join records natural join courses
where score is not null
order by cou_id asc,score desc
limit 5
offset 10;

-- 42. 查询选课学生的姓名和平均成绩(嵌套查询和连接查询)
select stu_name
	,平均成绩 
from students
	natural join (select stu_id
			,round(avg(score),1) as 平均成绩 
			from records
			group by stu_id) as 临时表;
-- 43. 查询学生的姓名和选课的数量(嵌套查询和连接查询)
select stu_name
	,选择数量
from students
	natural join (select stu_id
			,count(*) as 选择数量
			from records
			group by stu_id) as 临时表;
-- 44. 查询所有学生的姓名和选课数量(左外连接和嵌套查询)

-- 左外连接 :左表(写在join左边的表 )取到所有的数据,不满足连表条件的地方填充空值
-- outer可以省略 
-- left outer join / left join
-- 右外连接:右表(写在join右边的表 )取到所有的数据,不满足链表条件的地方填充空值
-- right outer join  / right join
-- 全外连接:左右两张表都要取到所有的数据,不满足连表条件的地方填充空值(MySQL不支持)
-- mysql实现全外连接的效果可以通过左外连接union右外连接的方式来实现连接

select stu_name as 姓名
	,coalesce(选择数量,0)
from students
	left outer join (select stu_id
			,count(*) as 选择数量
			from records
			group by stu_id) as 临时表
	on students.stu_id = 临时表.stu_id;

-- 45. 查询没有选课的学生的姓名(左外连接和数据筛选)
select stu_name as 姓名
	,rec_id as 流水号
from students left outer join records
		on students.stu_id = records.stu_id
where rec_id is null;

你可能感兴趣的:(MySQL,mysql,数据库,sql)