Bootstrap

MySQL 查询题型总结

MySQL 查询题型总结
### MySQL 3 
use `school`;

-- 查询所有学生的所有信息
select * from tb_student;
select  stu_id,
        stu_name,
        stu_addr
   from tb_student;

use school;
-- 查询学生的学号、姓名和籍贯(投影)
select stu_id as 学号,
       stu_name as 姓名,
       stu_addr as 籍贯 
	from tb_student;
-- alias _ 别名
-- 查询所有课程的名称及学分(投影和别名)
select stu_id as '学生编号',
       stu_name as '学生姓名'
  from tb_student;  

-- 查询所有女学生的姓名和出生日期(筛选)
select stu_name,
       stu_birth
  from tb_student
  where stu_sex = 0;

-- 查询籍贯为“四川成都”的女学生的姓名和出生日期(筛选)
select stu_name,
       stu_birth
	from tb_student
    where stu_sex = 0 and
          stu_addr = '四川成都';
          

-- 查询籍贯为“四川成都”或者性别是女的学生
select stu_name,
       stu_birth
	from tb_student
    where stu_sex = 0 or
          stu_addr = '四川成都';

-- 查询所有80后学生的姓名、性别和出生日期(筛选)
select stu_name,
	   stu_sex,
       stu_birth
	from tb_student
    where stu_birth>='1980-1-1' and
          stu_birth<='1990-1-1';
-- 或者使用betwee    and  
-- 可以做数学运算,性别+10,还可以做除法运算,加法,求余数,加减乘除求余运算,写筛选条件也可以写数学运算
select stu_name,
	   stu_sex +10,
       stu_birth
	from tb_student
    where stu_birth between '1980-1-1' and '1990-1-1';

-- 查询学分大于2的课程的名称和学分(筛选)
select cou_name as '课程名称',
       cou_credit as '课程学分'
	from tb_course
    where cou_credit > 2;

-- 查询学分是奇数的课程的名称和学分(筛选)
select cou_name ,
       cou_credit 
	from tb_course
    where cou_credit mod 2 <> 0;       -- 这两种方法都可以的
    -- where cou_credit % 2 <> 0 ;    -- mod 取余

-- 查询选择选了1111的课程考试成绩在90分以上的学生学号(筛选)
select stu_id
 from  tb_record
 where cou_id = 1111 and
       score > 90;

-- 查询名字叫“杨过”的学生的姓名和性别
select stu_name as '学生姓名',
-- case when then else end 分支结构
-- 使用if函数构造分支结构, if 是mysql方言,不建议使用,不适用于其他的数据库
     --  if(stu_sex ,'男','女') as 性别
       case stu_sex  when 1 then '男' when 0 then '女' else '未知' end  as '学生性别'  
  from tb_student
  where stu_name = '杨过';
  
--  ¥¥¥ 复习的时候,练习写的
select stu_name as '学生性别',
	   case stu_sex when 1 then '男' when 0 then '女' else '未知' end as '性别'
	from tb_student
    where stu_name = '杨过';
    
-- 查询姓“杨”的学生姓名和性别(模糊)
-- like是像的意思
-- 通配符 - wild card - 百搭牌
-- % 匹配0个或任意多个字符
-- _ 下划线精确匹配一个字符,如果要匹配两个字符,就写两个下划线
-- 方法1 使用 _ 来匹配,一个_匹配一个字符,两个_ _ 匹配两个字符
select stu_name,
       stu_sex
	from tb_student
    -- where stu_name like '杨%'; 
    where stu_name like '杨_' or
          stu_name like '杨__';   -- 两种方法都可以
-- 方法2 使用%来匹配
select stu_name,
       case stu_sex when 1 then '男' when 0 then '女' else '未知' end  as '性别'
  from tb_student
  where stu_name like '杨%';
  
-- 查询姓“杨”名字两个字的学生姓名和性别(模糊)
select stu_name,
       stu_sex
	from tb_student
    where stu_name like '杨_';
    
-- 查询姓“杨”名字三个字的学生姓名和性别(模糊)
select stu_name,
       stu_sex
	from tb_student
    where stu_name like '杨__';
    
-- 查询名字中有“不”字或“嫣”字的学生的姓名(模糊)
select stu_name,
       stu_sex
	from tb_student
    where stu_name like '%不%' or
		  stu_name like '%嫣%';
          
-- 方法2使用union 连接两个查询,把两个条件分开写。
select stu_name,
       stu_sex
	from tb_student
    where stu_name like '%不%'
union  -- union all是把集合的元素不去重,直接把数据组装起来,而union 是会去重的,
select stu_name,
       stu_sex
	from tb_student
    where stu_name like '%嫣%';
 -- 关系代数-以集合论、一阶谓词逻辑逻辑
 -- mysql没有交,差运算,只有并集运算。
 -- 使用正则表达式进行查询,在必知必会第9章。
 
 -- 查询姓“杨”名字三个字的学生姓名和性别(模糊)
 -- regexp  -  regular expression - 正则表达式
 select  stu_name
     from tb_student
     where stu_name regexp '[杨][\\u4e00-\\u9fa5]{1,2}';  # -- \表示转义,\u表示的是unicode编码。
 
-- 查询姓“杨”或姓“林”名字三个字的学生的姓名(正则表达式模糊查询)
select  stu_name
     from tb_student
     where stu_name regexp '[杨林][\\u4e00-\\u9fa5]{2}';
-- 查询没有录入籍贯的学生姓名(空值处理)  
-- 三值逻辑: true / false / unkown   <-----空值做任何运算的结果,结果仍然是空值,空值做关系运算,逻辑运算,会产生unkown,判断空或者非空,要写is null ,或者is not null。
-- 为空要写 is null ,不为空,写is not null
-- tirm --MYSQL函数- 修剪字符串两端的空格.
select stu_name
  from tb_student
  where stu_addr is null ;  -- sql关系运算,真假未知,
 
update  tb_student set stu_addr  = '' where stu_id = 3755;
-- 查询录入了籍贯的学生姓名(空值处理)
select stu_name
  from tb_student
  where stu_addr is not  null ; 
-- 如果字符串是空字符串
-- 下面查询没有籍贯的学生,包括字符串的值为空
select stu_name
  from tb_student
  where stu_addr is null or 
        stu_addr = '';   #可以查到两个学生记录

-- 下面查询有籍贯的学生,不包括字符串的值为空
select stu_name
  from tb_student
  where stu_addr is  not null and
        stu_addr <> ''; 
-- 如果查询的数据中,字符串是很多空格,以上方法任然查不出来。,要加函数trim(),如果要去掉左边的空格或数据,就使用leleading'什么内容'
-- 德摩根律
update tb_student set stu_addr = '   ' where stu_id = 3755;
-- 找地址空的
select stu_name
  from tb_student
  where stu_addr is null or 
        trim(stu_addr) = ''; 
-- 找地址非空
select stu_name
  from tb_student
  where stu_addr is not null and
        trim(stu_addr) <> ''; 
-- 查询学生选课的所有日期(去重)
-- distinct 去重
select distinct sel_date
  from tb_record;
  
-- 查询学生的籍贯(去重)
select distinct sel_date
  from tb_record
  where stu_addr is not null and
        trim(stu_addr) <>'';
-- 查询男学生的姓名和生日按年龄从大到小排列(排序)
-- asc ascending  -上升 - 从小到大
-- desc -- descending  - 下降 - 从大到小
select stu_name,
       stu_birth
	from tb_student
    where stu_sex = 1
	order by stu_birth asc, stu_id desc;
-- 时间日期函数
-- now() - 获取当前数据库服务器的时间
-- curdate() - current date - 获取当前日期
-- curtime()  --current time - 获取当前时间
-- datediff(dt1,dt2)
-- 数数值函数
-- floor() - 向下取整
--  ceiling() /ceil() - 向上取整
-- round()- 四舍五入
select now();  -- 当前时间日期
select curdate();  -- 当前日期
select curtime();  -- 当前时间
-- 补充:将上面的生日换算成年龄(日期函数、数值函数)
select stu_birth,
	   stu_name,
       floor(datediff(curdate(),stu_birth)/365) as '年龄'
  from tb_student
  where stu_sex = 1 order by 年龄 desc;
help functions;
help time;
-- 查询年龄最大的学生的出生日期(聚合函数) - 查询最小的生日
select min(stu_birth)
   from tb_student;
   

-- 查询年龄最小的学生的出生日期(聚合函数)  - 查询年龄最小的
select max(stu_birth)
   from tb_student;
-- 查询编号为1111的课程考试成绩的最高分(聚合函数)
select max(score)
   from tb_record
   where cou_id = 1111;   -- 95.0
-- 查询学号为1001的学生考试成绩的最低分(聚合函数)
select min(score)
   from tb_record
   where stu_id = 1001;  -- 87.5
-- 查询学号为1001的学生考试成绩的平均分(聚合函数)
-- 注意:聚合函数不会处理空值(null),即求和,计数不会考虑空值的。
-- 聚合函数有max/min/avg/sum/count
-- count(*) 统计所有的行数,count(score)统计所有的非空值
-- coalesce(x,y,z)返回参数中第一个非空值。
select round(avg(score),1)  -- 95.6
   from tb_record
   where stu_id = 1001;  -- 95.62500 --想要保留几位小数,使用round函数。
   
   
-- 查询学号为1001的学生考试成绩的平均分,如果有null值,null值算0分(聚合函数)
select round(avg(score),1)  -- 95.6
   from tb_record
   where stu_id = 1001;  -- 95.62500
   
-- 方法1
select sum(score)/count(*) 
   from tb_record
   where stu_id = 1001;  -- 76.50000
-- 方法2 ifnull --MYSQL函数,如果score是空值,就返回0,否则就是返回score.
select avg(ifnull(score,0)) 
   from tb_record
   where stu_id = 1001;  -- 76.5
-- 方法3 使用 coalesce  
select avg(coalesce(score,0))   -- 通用的
   from tb_record
   where stu_id = 1001;   -- 76.50000 
-- 方法4 
select avg(case when score is null then 0 else score end)
   from tb_record
   where stu_id = 1001;  -- 76.5000
-- Hao(jackfrued) 14:09:05
-- 获取描述性统计信息
-- 均值、中位数、分位数、最大值、最小值、极差(全距)、方差、标准差
-- 均值在数据大小比较几种的时候,有很好的代表性
-- 方差 :给误差(每个数据跟均值的差)的平方求平均值。
-- 总体方差:
-- 样本方差:
-- 方差越大,均值的代表性越弱,方差越小,均值的代表性越好。
-- 查询学号为1001的学生考试成绩的标准差(聚合函数)
-- MYSQL函数  - std
-- oracle函数 -  stddev
-- 标准SQL
-- 标准差SQL - stddev_pop / sttdev_samp  总体标准差与样本标准差
-- 标准方差SQL - var_pop / var_samp  总体方差与样本方差
-- population - 总体 / sample - 样本
-- MYSQL方言 - std 
-- 
select variance(score)
   from tb_record
   where stu_id = 1001;  -- 方差 26.17
   
select round(stddev(score),2)
   from tb_record
   where stu_id = 1001;  -- 标准差 5.12
select round(stddev(score),2)
   from tb_record
   where stu_id = 1002;    -- 11.5
-- 举例说明 样本方差和标准差的计算
select stddev_samp(score)
   from tb_record
   where stu_id = 1002;   -- 样本标准差16.263455967290593

select var_samp(score)
   from tb_record
   where stu_id = 1002;   -- 样本方差 264.5

select stddev_pop(score)
   from tb_record
   where stu_id = 1002;   -- 总体标准差11.5

select var_pop(score)
   from tb_record
   where stu_id = 1002;   -- 总体方差132.25
help functions;  --查函数
help 'Aggregate Functions and Modifiers';  -- 查聚合函数

-- 查询男女学生的人数(分组和聚合函数) - 根据性别统计人数 
-- 要学会在不同的维度拆解数据
select case stu_sex when 1 then '男'else '女' end as 性别,

         count(*) as 人数
	 from tb_student
     group by stu_sex;


-- 查询每个学院学生人数(分组和聚合函数)
select col_id as 学院,
count(*) as 人数
  from tb_student
  group by col_id;
  
-- 查询每个学院男女学生人数(分组和聚合函数)
select col_id as 学院编号, -- 别名不需要单引号
       case stu_sex when 1 then '男' else '女' end as 性别,
       count(*) as 人数
  from tb_student
  group by col_id,stu_sex;
-- 查询每个学生的学号和平均成绩(分组和聚合函数)
select stu_id as 学生学号,
		round(avg(score),1) as 平均分
  from tb_record
  group by stu_id;  
-- 听过学号分组,然后计算平均分
-- 查询平均成绩大于等于90分的学生的学号和平均成绩
select stu_id,
       avg(score) as '平均成绩'
	from tb_record
    group by stu_id
    having avg(score) >= 90; 
     
-- 查询1111、2222、3333三门课程平均成绩大于等于90分的学生的学号和平均成绩
select stu_id as 学号,
       cou_id as  课程编号,
       round(avg(score),1) as 平均成绩
	from tb_record
    where cou_id in (1111,2222,3333)
    group by stu_id
    having avg(score) >= 90;   

-- 查询年龄最大的学生的姓名(子查询/嵌套查询)
-- 以前的方法
select min(stu_birth)  -- 赋值不能用等号,等号表示相等,判断的,赋值要用海象运算符
  from tb_student;  -- 1985-04-17
-- 新的方法 
select @x := min(stu_birth)  -- 赋值不能用等号,等号表示相等,判断的,赋值要用海象运算符
  from tb_student;
select @x ;  -- 把值赋值给了@X
select stu_name
   from tb_student
   where stu_birth = @x;  -- 杨不悔
-- 方法2 subquery - 把一个查询结果作为另一个查询的一部分来使用!!! 
select stu_name
   from tb_student
   where stu_birth = (select min(stu_birth)  
                                 from tb_student);  -- 杨不悔
 
-- 查询选了两门以上的课程的学生姓名(子查询/分组条件/集合运算)
select stu_name
  from tb_student
  where stu_id in (select stu_id   
                          from tb_record 
                          group by stu_id
                          having count(*) > 2);

-- 学号在这个集合里面就要去把数据拿出来。也可以写成一下方法
-- any 是一个谓词,可以产生真和假 ,作用是只要和后面任意一个匹配上,就返回真。
-- all 是一个谓词,----> 所有的元素都匹配成功才返回true.
-- in 集合运算也称为一个谓词。
-- 自己理解的 any是只要匹配上,就会返回值,然后会把集合里面每一个都元素都进行匹配?
select stu_name
  from tb_student
  where stu_id = any (select stu_id   
                          from tb_record 
                          group by stu_id
                          having count(*) > 2);
%*
杨过
王语嫣
项少龙
*%
-- 查询学生的姓名、生日和所在学院名称 (连接/表查询--- 从多张表投影字段)

-- from 子句如果放多张表但是没有连接记录的条件就会形成一个笛卡尔积,
-- 通过连接条件可以多张表满足条件的记录连接起来
-- python -- > 包名.模块名.函数名 ---> 完全限定名
-- 列,表都可以别名 as 可以省略

-- from  a  import foo
-- from b import foo
-- import a
-- import b
-- a.foo
-- b.foo
select  stu_name,
        stu_birth,
        col_name
	-- from tb_student as t1,tb_college as t2  -- 给两张表换个名字
    -- where t1.col_id = t2.col_id;
    from tb_student as t1,tb_college as t2 
    where tb_student.col_id = tb_college.col_id;
 -- 或者使用 from 表1 iner join 表名2 on 条件   ;
 select  stu_name,
        stu_birth,
        col_name
    from tb_student inner join tb_college on tb_student.col_id = tb_college.col_id ;
 
    
-- 查询学生姓名、课程名称以及成绩(连接查询/联结查询)
select stu_name,
	   cou_name,
       score
	from tb_student as t1,tb_course as t2,tb_record as t3
	where t1.stu_id = t3.stu_id and
          t2.cou_id = t3.cou_id and
          score is not null
  -- 方法2 内连接  使用 inner join  on 
  -- Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'nul' at line 5

 select stu_name,
	    cou_name,
        score
	from tb_student inner join tb_record on tb_student.stu_id = tb_record.stu_id inner join tb_course  on tb_course.cou_id = tb_record.cou_id
	where  score is not null ;
  -- 注意: 写时候on 后面的连接条件的时候,一定要注意对应关系。
  
  -- 方法3 自然连接 表1 natural join 表2 ,如果有同名列,就会连接,如果没有同名列,就会产生笛卡尔积。
  select stu_name,
	     cou_name,
         score
	from tb_student natural join tb_course natural join tb_record 
	where  score is not null;
  
  
-- 补充:上面的查询结果取前5条数据(分页查询)

-- limit 数字 只拿前几条
-- offset 数字  --- 跳过指定数字个 ,分页数据
 select stu_name,
	     cou_name,
         score
	from tb_student natural join tb_course natural join tb_record 
	where  score is not null
    order by cou_id asc ,score desc
    limit 5
    offset 10; 
 -- limit 数字1,数字2   --- 跳过数字1个数据,拿数字2个数据   。
 -- 方法2 使用limit 数字1,数字2
 select stu_name,
	     cou_name,
         score
	from tb_student natural join tb_course natural join tb_record 
	where  score is not null
    order by cou_id asc ,score desc
    limit 10 , 5;
    
-- 补充:上面的查询结果取第6-10条数据(分页查询)
use school;

 select stu_name,
	     cou_name,
         score
	from tb_student natural join tb_course natural join tb_record 
	where  score is not null
    order by cou_id asc ,score desc
    limit 5 , 5;
-- 补充:上面的查询结果取第11-15条数据(分页查询)
 select stu_name,
	     cou_name,
         score
	from tb_student natural join tb_course natural join tb_record 
	where  score is not null
    order by cou_id asc ,score desc
    limit 10 , 5;
    
-- 查询选课学生的姓名和平均成绩(子查询和连接查询)
select stu_name ,
       avg_score
	from tb_student natural join (select stu_id,
									  round(avg(score),1) as avg_score
                                      from tb_record

                                      group by stu_id) as tb_ave;
select stu_name as 学生姓名,
       round(avg(score),1) as 平均成绩
	from tb_student natural join  tb_record
    group by stu_id;


-- 查询学生的姓名和选课的数量 (只能查到选了课的学生的姓名和数量,还有三个没有选课的学生,不会查到)
-- 方式1 使用两个表的自然连接,是通过学号
select stu_name as 学生姓名,
       count(*) as 选课数量
	from tb_student natural join  tb_record
    group by stu_id;
    
 -- 方式2   使用内连接
 select stu_name as 学生姓名,
            count as 选课数量
	from tb_student inner join  selectgroup by stu_id;
 
-- 查询每个学生的姓名和选课数量(左外连接和子查询)

-- 内连接/自然连接:只会将两张表满足连表条件的记录取到
;