Hive全实现经典五十题(持续优化)

学生课程成绩老师,四张表

  • 学生表

在这里插入图片描述

  • 成绩表

在这里插入图片描述

  • 课程表

在这里插入图片描述

  • 老师表

在这里插入图片描述

  1. 查询"01"课程比"02"课程成绩高的学生的信息及课程分数

    //连接表时对连接的表加条件
    select s.s_name,s.s_id,s.s_birth,s.s_sex,sc1.s_score
    from student s
    left join score sc1
    on s.s_id=sc1.s_id and sc1.c_id=01
    left join score sc2
    on s.s_id=sc2.s_id and sc2.c_id=02
    where sc1.s_score>sc2.s_score;
    //
    select sc1.s_id,sc1.c_id,sc1.s_score
    from
    (
    select *
    from score where c_id=01
    )sc1
    left join 
    (
    select *
    from score where c_id=02
    )sc2
    on sc1.s_id=sc2.s_id
    where sc1.s_score>sc2.s_score
    
  2. 查询"01"课程比"02"课程成绩低的学生的信息及课程分数

    select s.s_name,s.s_id,s.s_birth,s.s_sex,sc1.s_score
    from student s
    left join score sc1
    on s.s_id=sc1.s_id and sc1.c_id=01
    left join score sc2
    on s.s_id=sc2.s_id and sc2.c_id=02
    where sc1.s_score < sc2.s_score;
    
    select sc1.s_id,sc1.c_id,sc1.s_score
    from
    (
    select *
    from score where c_id=01
    )sc1
    left join 
    (
    select *
    from score where c_id=02
    )sc2
    on sc1.s_id=sc2.s_id
    where sc1.s_score<sc2.s_score
    
  3. 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

    select s.s_id,s.s_name,avg(sc.s_score) avg_score
    from student s
    left join score sc
    on s.s_id=sc.s_id
    group by s.s_id,s.s_name
    having avg(sc.s_score)>60;
    -一步应该最高效了普通办法
    
  4. 查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩
    – (包括有成绩的和无成绩的)

    select s.s_id,s.s_name,avg(sc.s_score) avg_score
    from student s
    left join score sc
    on s.s_id=sc.s_id
    group by s.s_id,s.s_name
    having avg(sc.s_score)<60;
    
  5. 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩

    select s.s_id,s.s_name,count(*) countSelect,sum(sc.s_score) sumScore
    from student s
    left join score sc
    on s.s_id=sc.s_id
    group by s.s_id,s.s_name;
    
  6. 查询"李"姓老师的数量

    select count(*) from teacher where t_name like "李%";
    
  7. 查询学过"张三"老师授课的同学的信息

    //打出后三张大表,student直接join
    select *
    from student s
    where s.s_id in(
    SELECT sc.s_id
    from score sc
    LEFT JOIN course co 
    ON sc.c_id=co.c_id 
    LEFT JOIN teacher te 
    ON co.t_id=te.t_id
    where t_name='张三'
    );
    
    
    Launching Job 3 out of 3
    Time taken: 3.627 seconds, Fetched: 6 row(s)
    
    //
    select *
    from student s
    where s.s_id in
    (
    select sc.s_id
    from score sc
    join
    (
    select c.c_id
    from course c
    where c.t_id in
    (
    select t.t_id
    from teacher t
    where t.t_name='张三'
    )
    )t2
    on sc.c_id=t2.c_id
    )
    
    
    //
    select *
    from student s
    where exists
    (
    select sc.s_id
    from score sc
    join
    (
    select c.c_id
    from course c
    where c.t_id in
    (
    select t.t_id
    from teacher t
    where t.t_name='张三'
    )
    )t2
    on sc.c_id=t2.c_id
    where s.s_id=sc.s_id
    )
    
    //
    SELECT stu.* 
    FROM student stu 
    JOIN score sc 
    ON stu.s_id=sc.s_id 
    JOIN course co 
    ON sc.c_id=co.c_id 
    JOIN teacher te 
    ON co.t_id=te.t_id 
    WHERE t_name='张三'
    
    
    
    
    //全连接法
    SELECT stu.s_id,stu.s_name,stu.s_birth,stu.s_sex
    FROM student stu 
    LEFT JOIN score sc 
    ON stu.s_id=sc.s_id 
    LEFT JOIN course co 
    ON sc.c_id=co.c_id 
    LEFT JOIN teacher te 
    ON co.t_id=te.t_id
    where t_name='张三';
    
    Launching Job 3 out of 3
    Time taken: 3.693 seconds, Fetched: 6 row(s)
    
    //
    select s.s_id,s.s_name,s.s_birth,s.s_sex
    from student s,
    (
    select
    s.s_id
    from score s
    left join
    (
    select c.c_id
    from course c,(select t_id tid from teacher where t_name='张三')t
    where c.t_id=t.tid
    )t2
    on s.c_id=t2.c_id
    where s.c_id=t2.c_id
    )t3
    where s.s_id=t3.s_id
    
    Launching Job 3 out of 3
    Time taken: 3.689 seconds, Fetched: 6 row(s)
    
  8. 查询没学过"张三"老师授课的同学的信息

    select *
    from student s
    where s.s_id not in(
    SELECT stu.s_id
    FROM student stu 
    LEFT JOIN score sc 
    ON stu.s_id=sc.s_id 
    LEFT JOIN course co 
    ON sc.c_id=co.c_id 
    LEFT JOIN teacher te 
    ON co.t_id=te.t_id
    where t_name='张三'
    );
    
    Launching Job 9 out of 9
    Time taken: 10.695 seconds, Fetched: 2 row(s)
    
    select *
    from student s
    where s.s_id not in(
    SELECT sc.s_id
    from score sc
    LEFT JOIN course co 
    ON sc.c_id=co.c_id 
    LEFT JOIN teacher te 
    ON co.t_id=te.t_id
    where t_name='张三'
    );
    
    Launching Job 7 out of 7
    Time taken: 8.351 seconds, Fetched: 2 row(s)
    
  9. 查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

    select *
    from student s
    left join score sc1
    on s.s_id=sc1.s_id and sc1.c_id=01
    left join score sc2
    on s.s_id=sc2.s_id and sc2.c_id=02
    where sc1.s_score is not null and sc2.s_score is not null;
    
  10. 查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

    select s.s_id,s.s_name,s.s_birth,s.s_sex
    from student s
    left join score sc1
    on s.s_id=sc1.s_id and sc1.c_id=01
    left join score sc2
    on s.s_id=sc2.s_id and sc2.c_id=02
    where sc1.s_score is not null and sc2.s_score is null;
    
  11. 查询没有学全所有课程的同学的信息

    select sc.s_id
    from score sc,(select count(*) cou from course) cou_course
    group by sc.s_id,cou_course.cou
    having count(sc.s_score)<cou_course.cou
    
  12. 查询至少有一门课与学号为"01"的同学所学相同的同学的信息

    select s.*
    from student s
    left join score sc1
    on s.s_id=sc1.s_id and sc1.c_id='01'
    left join score sc2
    on s.s_id=sc2.s_id and sc2.c_id='02'
    left join score sc3
    on s.s_id=sc3.s_id and sc3.c_id='03'
    where sc1.c_id!=null or sc2.c_id!=null or sc3.c_id!=null and s.s_id!='01'
    ;
    
    select distinct(s.s_name),s.s_sex,s.s_birth,s.s_id
    from student s
    join score sc
    on s.s_id=sc.s_id
    where s.s_id!='01' and sc.c_id in
    (
    select
    c_id
    from score 
    where s_id='01'
    )
    
  13. 查询和"01"号的同学学习的课程完全相同的其他同学的信息

    //将01同学的数课程转化为数组和其他所有同学按照课程转化为数组的表join
    select t1.s_name,t1.s_id
    from
    (
    select s.s_name,s.s_id,collect_list(sc.c_id) arr_cid
    from student s
    join score sc
    on s.s_id=sc.s_id
    group by s.s_name,s.s_id
    )t1
    join
    (
    select
    collect_list(c_id) arr_cid
    from score 
    where s_id='01'
    )t2
    on t1.arr_cid=t2.arr_cid
    where t1.s_id!='01'
    
  14. 查询没学过"张三"老师讲授的任一门课程的学生姓名

    select *
    from student s
    where s.s_id not in(
    SELECT sc.s_id
    from score sc
    LEFT JOIN course co 
    ON sc.c_id=co.c_id 
    LEFT JOIN teacher te 
    ON co.t_id=te.t_id
    where t_name='张三'
    );
    
  15. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

    //先得到不及格的所有同学然后分组统计
    select t.s_name,t.s_id,round(avg(t.s_score),2)
    from
    (
    select s.s_name,s.s_id,sc.s_score
    from
    student s
    join score sc
    on s.s_id=sc.s_id
    where sc.s_score < 60
    )t
    group by t.s_id,t.s_name
    having count(*)>=2
    
  16. 检索"01"课程分数小于60,按分数降序排列的学生信息

    SELECT *
    FROM student s
    LEFT JOIN score sc
    ON s.s_id=sc.s_id
    WHERE c_id='01'
    AND s_score<60
    ORDER BY  s_score
    
  17. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

    //直接窗口函数取最前面到最后面的平均值
    select s_id,s_score,
    round(avg(nvl(s_score,0)) over(partition by s_id order by s_score desc rows between unbounded preceding and unbounded following ),1) avg_sc
    from score 
    
  18. 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率
    –及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

    //按照成绩列将满足条件置为1不满足为0,然后进行求和就得出了每一个条件下的总人数,然后除以总人数
    
    select c.c_id,c.c_name,
    round(sum(case when sc.s_score >= 90 then 1 else 0 end)/count(*),1) exce,
    round(sum(case when sc.s_score>=80 and sc.s_score<90 then 1 else 0 end)/count(*),1) good,
    round(sum(case when sc.s_score >=70 and sc.s_score <80 then 1 else 0 end)/count(*),1) mid,
    round(sum(case when sc.s_score >= 60 and sc.s_score <70 then 1 else 0 end)/count(*),1) seve,
    max(sc.s_score) max_sc,
    min(sc.s_score) min_sc,
    round(avg(sc.s_score),1) avg_sc
    from course c
    left join score sc
    on c.c_id=sc.c_id
    group by c.c_id,c.c_name;
    
    
    //
    
    {"good":"0.33","notseve":"0.33","mid":"0.33"}
    {"good":"0.5","seve":"0.17","notseve":"0.17","exce":"0.17"} 
    {"good":"0.33","notseve":"0.33","exce":"0.33"}
    
    //
    一个新列是成绩的分类,然后是max等其他,将分类和人数除以总人数合并(cancat),然后将每一科的所有拼接的字符串转为list然后拼为总字符串然后转为map,
    
    select t2.c_id,
    t2.c_name,
    t2.max_sc,
    t2.min_sc,
    t2.avg_sc,
    nvl(t2.type['exce'],0) exec,
    nvl(t2.type['good'],0) good,
    nvl(t2.type['mid'],0) mid,
    nvl(t2.type['seve'],0) seve
    from
    (
    select t1.c_id,
    t1.c_name,
    str_to_map(concat_ws(',',collect_list(t1.type)),',','_') type,
    t1.max_sc,
    t1.min_sc,
    t1.avg_sc
    from
    (
    select t.c_id,
    t.c_name,
    concat(t.type,'_',round(count(*)/t.cou_,2)) type,
    t.max_sc,
    t.min_sc,
    t.avg_sc
    from
    (
    select c.c_id,c.c_name,
    case when sc.s_score >= 90 then 'exce' 
    when sc.s_score>=80 and sc.s_score<90 then 'good'
    when sc.s_score >=70 and sc.s_score <80 then 'mid'
    when sc.s_score >= 60 and sc.s_score <70 then 'seve'
    else 'notseve' end type,
    count(c.c_name) over(partition by c.c_name) cou_,
    max(sc.s_score) over(partition by c.c_id) max_sc,
    min(sc.s_score) over(partition by c.c_id) min_sc,
    round(avg(sc.s_score) over(partition by c.c_id),1) avg_sc
    from course c
    left join score sc
    on c.c_id=sc.c_id
    )t
    group by t.c_id,t.c_name,t.type,t.cou_,t.max_sc,t.min_sc,t.avg_sc
    )t1
    group by t1.c_id,t1.c_name,t1.max_sc,t1.min_sc,t1.avg_sc
    )t2
    group by t2.c_id,t2.c_name,t2.max_sc,t2.min_sc,t2.avg_sc,t2.type
    
  19. 按各科成绩进行排序,并显示排名(实现不完全)

    select s.*,rank() over(partition by s.c_id order by s.s_score) rank
    from score s
    
  20. 查询学生的总成绩并进行排名

    select s_name,sum(nvl(s_score,0)) su_sc
    from student s 
    left join score sc
    on s.s_id=sc.s_id
    group by s_name
    order by su_sc desc
    
  21. 查询不同老师所教不同课程平均分从高到低显示

    select c.t_id,c.c_name,round(avg(nvl(sc.s_score,0)),2) avg_score
    from course c
    left join score sc
    on c.c_id=sc.c_id
    group by c.t_id,c.c_name
    order by avg_score desc
    
  22. 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

    select
    t1.*
    from
    (
    select s.*,sc.c_id,sc.s_score,
    row_number() over(partition by sc.c_id order by sc.s_score desc) rank
    from score sc
    left join student s
    on sc.s_id=s.s_id
    )t1
    where t1.rank>1 and rank <=3
    
  23. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比

    select c.c_id,c.c_name,
    round(sum(case when sc.s_score>85 and sc.s_score <=100 then 1 else 0 end)/count(*),1) `[100-85]`,
    round(sum(case when sc.s_score>85 and sc.s_score <=85 then 1 else 0 end)/count(*),1) `[85-70]`,
    round(sum(case when sc.s_score>60 and sc.s_score <=70 then 1 else 0 end)/count(*),1) `[70-60]`,
    round(sum(case when sc.s_score>0 and sc.s_score <=60 then 1 else 0 end)/count(*),1) `[0-60]`
    from score sc
    join course c
    on sc.c_id=c.c_id
    group by c.c_id,c.c_name
    
  24. 查询学生平均成绩及其名次

    select sc.s_id,
    avg(if null(sc.s_score,0)) avg_sc ,
    row_number() over(sort by sc.avg)
    from score sc
    group by sc.s_id
    
  25. 查询各科成绩前三名的记录

    select t.*
    from
    (
    select sc.*,
    row_number() over(partition by sc.c_id order by sc.s_score desc) rank
    from score sc
    )t
    where t.rank <=3;
    
  26. 查询每门课程被选修的学生数

    select c_id,count(*) cou_per
    from score
    group by c_id
    
  27. 查询出只有两门课程的全部学生的学号和姓名

    select s_name,s.s_id
    from score sc
    left join student s
    on sc.s_id=s.s_id
    group by s.s_id,s_name
    having count(*)=2;
    
  28. 查询男生、女生人数

    SELECT s_sex,COUNT(*) cou_per
    FROM student
    GROUP BY s_sex;
    
  29. 查询名字中含有"风"字的学生信息

    select *
    from student
    where s_name like '%风%'
    
  30. 查询同名同性学生名单,并统计同名人数

    select s.s_name,s.s_sex,count(*) cou_per
    from student s
    group by s.s_name,s.s_sex
    
  31. 查询1990年出生的学生名单

    //
    SELECT s_name 
    FROM student
    WHERE s_birth LIKE '1990%'
    
    //
    select s_name
    from student
    where year(s_birth)='1990'
    
  32. 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列

    select avg(s_score)
    from score
    group by c_id
    order by avg(s_score) desc, (c_id) avg
    
  33. 查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩

    select s.s_id,s.s_name,avg(sc.s_score) avg_sc
    from student s
    left join score sc
    on s.s_id = sc.s_id
    group by sc.s_score
    having avg_sc>=85
    
  34. 查询课程名称为"数学",且分数低于60的学生姓名和分数

    SELECT s_name,s_score
    FROM student stu LEFT JOIN score sc ON stu.s_id=sc.s_id
    LEFT JOIN course co ON sc.c_id=co.c_id
    WHERE s_score < 60 AND c_name ='数学'
    
  35. 查询所有学生的课程及分数情况;

    SELECT s_name,c_name,s_score
    FROM student stu 
    LEFT JOIN score sc 
    ON stu.s_id=sc.s_id
    
  36. 查询任何一门课程成绩在70分以上的姓名、课程名称和分数;

    select s.s_name,c.c_name,sc.s_score
    FROM student s
    LEFT JOIN score sc 
    ON s.s_id=sc.s_id
    LEFT JOIN course c 
    ON sc.c_id=c.c_id
    where sc.s_score>70
    
  37. 查询不及格的课程

    //
    SELECT s.s_name,sc.c_name,sc.s_score
    FROM student s
    LEFT JOIN score sc 
    ON s.s_id=sc.s_id
    WHERE sc.s_score<60
    
    //
    select c_id,avg(score)
    from score 
    group by c_id
    having avg(score)<=60
    
  38. 查询课程编号为01且课程成绩在80分以上的学生的学号和姓名;

    SELECT stu.s_id,s_name
    FROM student stu 
    LEFT JOIN score sc 
    ON stu.s_id=sc.s_id
    LEFT JOIN course co 
    ON sc.c_id=co.c_id
    WHERE co.c_id=01
    AND s_score>80
    
  39. 求每门课程的学生人数

    select c_id,count(*) cou_per
    score
    group by c_id
    
  40. 查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩

    select s.*,sc.s_score
    FROM student s 
    LEFT JOIN score sc 
    ON s.s_id=sc.s_id 
    LEFT JOIN course c 
    ON sc.c_id=c.c_id 
    LEFT JOIN teacher te 
    ON c.t_id=te.t_id
    where te.t_name='张三'
    order by sc.s_score
    limit 1;
    
  41. 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

    select distinct(sc1.s_id),sc1.c_id,sc1.s_score
    from score sc1,score sc2
    where sc1.c_id!=sc2.c_id 
    and sc1.s_score=sc2.s_score
    
  42. 查询每门功成绩最好的前两名

    select
    t.s_id,t.c_id,
    t.rank
    from
    (
    select
    s_id,c_id,
    row_number() over(partition by c_id order by s_score desc) rank
    from score
    )t
    where t.rank <= 2
    
  43. 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

    SELECT c_id,COUNT(*)
    FROM score
    GROUP BY c_id
    HAVING COUNT(*)>5
    ORDER BY COUNT(*) DESC,c_id ASC
    
  44. 检索至少选修两门课程的学生学号

    select sc.s_id
    from score sc
    group by s.s_id
    having count(*)>=2
    
  45. 查询选修了全部课程的学生信息

    select
    from score sc,count(select count(*) cou_per from course c) cou_per
    where 
    group by sc.s_id
    having count(*) > cou_per
    
  46. 查询各学生的年龄

    methon1:
    自定义UDF函数上传使用
    public class AgeCalculate extends UDF {
        public int evaluate(String str) {
            int age = 0;
            if (str.matches("\\d{4}(\\-|\\/|.)\\d{1,2}\\1\\d{1,2}")) {
                String[] dateStr = str.split("-");
                int year = Integer.parseInt(dateStr[0]);
                int month = Integer.parseInt(dateStr[1]);
                int day = Integer.parseInt(dateStr[2]);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String nowDate = simpleDateFormat.format(new Date());
                String[] now = nowDate.split("-");
                int nowYear = Integer.parseInt(now[0]);
                int nowmonth = Integer.parseInt(now[1]);
                int nowDay = Integer.parseInt(now[2]);
                if (nowmonth==month && nowDay <= day ){
                    age=nowYear-year-1;
                }else if (nowmonth< month){
                    age=nowYear-year-1;
                }else {
                    age=nowYear-year;
                }
            } else {
                System.out.println("you input don't matche str");
            }
            return age;
        }
    
        public static void main(String[] args) {
            new AgeCalculate().evaluate("2010-9-2");
        }
    
    }
    
    //
    methon2:
    select s_name,from_unixtime(curdate,'yyyy')-year(s_birth) 'age'
    from student  
    
  47. 查询本周过生日的学生

    select *
    from student
    where weekofyear(s_birth)=weekofyear(current_date());
    
  48. 查询下周过生日的学生

    select *
    from student
    where weekofyear(s_birth)=weekofyear(current_date())+1;
    
  49. 查询本月过生日的学生

    select * from student where month(s_birth)=month(current_date);
    
  50. 查询下月过生日的学生

    select * from student where month(s_birth)=month(current_date)+1;
    
发布了10 篇原创文章 · 获赞 4 · 访问量 1935

猜你喜欢

转载自blog.csdn.net/Kevin__Durant/article/details/101364427