考试分数(二、三)

1.牛客每次考试完,都会有一个成绩表(grade),如下:

id

job

score

1

C++

11001

2

C++

10000

3

C++

9000

4

Java

12000

5

Java

13000

6

JS

12000

7

JS

11000

8

JS

9999

9

Java

12500

第1行表示用户id为1的用户选择了C++岗位并且考了11001分

。。。

第8行表示用户id为8的用户选择了前端岗位并且考了9999分

请你写一个sql语句查询用户分数大于其所在工作(job)分数的平均分的所有grade的属性,并且以id的升序排序,如下:

id

job

score

1

C++

11001

5

Java

13000

6

JS

12000

7

JS

11000

(注意: sqlite 1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5,sqlite四舍五入的函数为round)

 

我的方法:

select *

from grade t1

where score >(select avg(score) from grade where job = t1.job)

group by id

 

方法一:子查询将t1,t2表进行关联

select id,job, score

from `grade` t1

where score >

  (select avg(score) from `grade` t2 where t1.job = t2.job)

order by 1 ;

 

 

 

方法二:表连接

select id, t1.job, score

from `grade` t1

  left join

  (select job,avg(score)av from `grade` group by 1)t2

  on t1.job = t2.job

where t1.score > t2.av

order by 1 ;

 

方法三:窗口函数

select id, job, score

from

  (select id,job,score,

    avg(score)over(partition by job)av

   from `grade`

  )t1

where score > av

order by 1 ;

 

经典错误:

select * from grade

group by job

having score>avg(score)

order by id asc;

使用group by进行分组结果变成了三条

 

然后再使用score>avg(score)筛选,结果变成了

 

 

 

 题目二:牛客每次举办企业笔试的时候,企业一般都会有不同的语言岗位,比如C++工程师,JAVA工程师,Python工程师,每个用户笔试完有不同的分数,现在有一个分数(grade)表简化如下:

id language_id score
1 1 12000
2 1 13000
3 2 11000
4 2 10000
5 3 11000
6 1 11000
7 2 11000
第1行表示用户id为1的选择了language_id为1岗位的最后考试完的分数为12000,
....
第7行表示用户id为7的选择了language_id为2岗位的最后考试完的分数为11000,

不同的语言岗位(language)表简化如下:
id name
1 C++
2 JAVA
3 Python

请你找出每个岗位分数排名前2名的用户,得到的结果先按照language的name升序排序,再按照积分降序排序,最后按照grade的id升序排序,得到结果如下:
id name score
2 C++ 13000
1 C++ 12000
3 JAVA 11000
7 JAVA 11000
4 JAVA 10000
5 Python 11000

我的思路:

select id,name,score from

(select grade.id,name,score,

    dense_rank()over(partition by name order by score desc)ranking

from grade,language

where grade.language_id = language.id

)t

where ranking <=2

 

错误:窗口函数加了id排序出错,因为只用score函数认为score为11000和11000的排名相同,如果加上name,id,只有name,id,score相同的函数才会认为是排名一样,所以下面方法错误,结果输出不完整。

select id,name,score from

(select grade.id,name,score,

    dense_rank()over(partition by name order by score desc,grade.id)ranking

from grade,language

where grade.language_id = language.id

)t

where ranking <=2

 

 

 

方法二:自连接

单纯自连接:有可能存在同分的情况所以要用<=,并且不是输出所有岗位的,而是要分岗位输出,要分组,故要用g1.language_id=g2.language_id.

SELECT g1.language_id,g1.id,g1.score

    FROM grade AS g1, grade AS g2

    WHERE g1.score<=g2.score

AND g1.language_id=g2.language_id

 

加了group by 之后

SELECT g1.language_id,g1.id,g1.score

    FROM grade AS g1, grade AS g2

    WHERE g1.score<=g2.score

    AND g1.language_id=g2.language_id

GROUP BY g1.language_id,g1.id

 

加了having之后

SELECT g1.language_id,g1.id,g1.score

    FROM grade AS g1, grade AS g2

    WHERE g1.score<=g2.score

    AND g1.language_id=g2.language_id

    GROUP BY g1.language_id,g1.id

HAVING COUNT(DISTINCT g2.score)<=2

 

综合语句如下:

SELECT a.id,name,score

FROM (

    SELECT g1.language_id,g1.id,g1.score

    FROM grade AS g1, grade AS g2

    WHERE g1.score<=g2.score

    AND g1.language_id=g2.language_id

    GROUP BY g1.language_id,g1.id

    HAVING COUNT(DISTINCT g2.score)<=2)AS a

INNER JOIN language

ON a.language_id=language.id

ORDER BY name,score DESC,a.id

结果:

 

 

 

posted @ 2022-08-24 11:56  萧六弟  阅读(90)  评论(0)    收藏  举报