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;
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章