Oracle sql to find difference between the average and the lowest average - sql

(Easy) Find the difference between each student’s average grade and the best average grade in his group.
pls help....
i am trying hard to figure out the problem still not solved.
i should use partition function and how to generate the differences between the best student average in a group to that of the lower grades students.
this is my query,,
**select
students.st_id,students.st_group,
rank() over (partition by students.st_group order by avg(grades.g_grade) desc ) as ranking ,
lead(avg(grades.g_grade), 1, 0) OVER (PARTITION BY students.st_group ORDER BY avg(grades.g_grade) DESC NULLS LAST) DifferencebetweenHigheraverage,
avg(grades.g_grade)
from grades left join students on grades.g_student=students.st_id
group by students.st_id,students.st_group
having students.st_group in (1,2,3);**
Pls help.......

if in the table STUDENT_GRADES, i have attributes
ST_ID
ST_GROUP
ST_GRADE
select query to get student's difference from maximum grade among his group is
with MAXGRADES as (select ST_GROUP, max(ST_GRADE) as MAX from STUDENT_GRADES)
select ST_ID, ST_GRADE - MAX as DIFF from STUDENT_GRADES inner join MAXGRADES using(ST_GROUP)

Related

SQL Select all MIN Values for each group

So I need to select all the students, having the minimum grade for each prof. For example, if Augustinus had two students with grade 1.0, then I would like to see both in the result.
Table of my data
What the result could look like, if the LIMIT was set to 10
So what I basically want is to see the best students that each prof has.
What I have tried is the following:
SELECT professor, student, min(note)
FROM temp
GROUP BY professor
ORDER BY note
The problem of course being that I only get one minimum value for each prof and not all minimum values.
*temp is just the table name
One way to solve these types of problems is to use a subquery to rank the grades for each class in a descending order. This involves a window function. With a second query you can limit the results based on your criteria of 10.
SELECT professor, student, note
FROM
(
SELECT professor,student,note,
row_number() over(partition by professor order by note desc) as downwardrank
) as rankings
WHERE
downwardrank <= 10
Just found a solution myself:
SELECT professor, student, note
FROM temp
WHERE (professor, note) IN
(SELECT professor, min(note)
FROM temp
GROUP BY professor
ORDER BY note)
ORDER BY note, professor, student
LIMIT 10

Counting the unique values after group by clause

I need to count students in every major for an academic year. There are three terms in a year. One student declares a different major in every terms . I need to take the last major he/she declared and count all the students in a major. So only one student for one major.
When I do group by by major, I can't avoid the duplicates.
I have only one table. It has everything I need.
I wrote this code. And It gives me the duplicated count.
SELECT MAJR_CODE, MAJR_DESC, COUNT(DISTINCT ID_KEY)
FROM STUDENT_ENROLLMENT
WHERE TERM in ('201830','201910','201920')
and REGISTERED='Y'
GROUP BY MAJR_CODE, MAJR_DESC
ORDER BY MAJR_CODE
How can I get the result I want?
You can use window functions to get the data for the most recent term:
SELECT MAJR_CODE, MAJR_DESC, COUNT(*)
FROM (SELECT se.*, ROW_NUMBER() OVER (PARTITION BY ID_KEY DESC ORDER BY TERM DESC) as seqnum
FROM STUDENT_ENROLLMENT se
WHERE TERM in ('201830', '201910', '201920') AND
REGISTERED = 'Y'
) se
WHERE seqnum = 1
GROUP BY MAJR_CODE, MAJR_DESC
ORDER BY MAJR_CODE

Hive Script, DISTINCT with SUM

I am trying to distinct and then find the count of the teams a player played for in any single season and number of teams he played for. This is tripping me up and ofcourse i have a sample down below(2nd) one. The first ones is my failed attempt
SELECT o.id,o.year,COUNT(DISTINCT(o.team)) b JOIN
(SELECT id, year, team FROM batting
GROUP BY id,year,team
ORDER BY id DESC
LIMIT 25) o
0.id =b.id;
SELECT id, year, team FROM batting
GROUP BY id,year,team
ORDER BY id DESC
LIMIT 25;
produces
IGNORE the ^A, i think they represent either space or comma, just column seperatpr
Get the count of teams for each player for each year and order by the count desc,get the 1 row
SELECT id, year, COUNT(DISTINCT(team)) FROM batting
GROUP BY id,year
ORDER BY COUNT(DISTINCT(team)) DESC
LIMIT 1;

Trying to figure out how to join these queries

I have a table named grades. A column named Students, Practical, Written. I am trying to figure out the top 5 students by total score on the test. Here are the queries that I have not sure how to join them correctly. I am using oracle 11g.
This get's me the total sums from each student:
SELECT Student, Practical, Written, (Practical+Written) AS SumColumn
FROM Grades;
This gets the top 5 students:
SELECT Student
FROM ( SELECT Student,
, DENSE_RANK() OVER (ORDER BY Score DESC) as Score_dr
FROM Grades )
WHERE Student_dr <= 5
order by Student_dr;
The approach I prefer is data-centric, rather than row-position centric:
SELECT g.Student, g.Practical, g.Written, (g.Practical+g.Written) AS SumColumn
FROM Grades g
LEFT JOIN Grades g2 on g2.Practical+g2.Written > g.Practical+g.Written
GROUP BY g.Student, g.Practical, g.Written, (g.Practical+g.Written) AS SumColumn
HAVING COUNT(*) < 5
ORDER BY g.Practical+g.Written DESC
This works by joining with all students that have greater scores, then using a HAVING clause to filter out those that have less than 5 with a greater score - giving you the top 5.
The left join is needed to return the top scorer(s), which have no other students with greater scores to join to.
Ties are all returned, leading to more than 5 rows in the case of a tie for 5th.
By not using row position logic, which varies from darabase to database, this query is also completely portable.
Note that the ORDER BY is optional.
With Oracle's PLSQL you can do:
SELECT score.Student, Practical, Written, (Practical+Written) as SumColumn
FROM ( SELECT Student, DENSE_RANK() OVER (ORDER BY Score DESC) as Score_dr
FROM VOTES ) as score, students
WHERE score.score_dr <= 5
and score.Student = students.Student
order by score.Score_dr;
You can easily include the projection of the first query in the sub-query of the second.
SELECT Student
, Practical
, Written
, tot_score
FROM (
SELECT Student
, Practical
, Written
, (Practical+Written) AS tot_score
, DENSE_RANK() OVER (ORDER BY (Practical+Written) DESC) as Score_dr
FROM Grades
)
WHERE Student_dr <= 5
order by Student_dr;
One virtue of analytic functions is that we can just use them in any query. This distinguishes them from aggregate functions, where we need to include all non-aggregate columns in the GROUP BY clause (at least with Oracle).

How to get the MAX result even if the MAX is different

I have a code where I am pulling language knowledge and each employee has a plan year, they do not all complete them each year and in order to get their most recent one I use the MAX for plan year. Now one of the criteria is whether or not they are willing to move over seas, the issue arises that it will bring up their most recent YES and most recent NO and I just need their most recent plan year whether it be yes or no, I am having difficulty troubleshooting this. The code is as follows:
SELECT Employee_ID, Accept_International_Assignment, MAX(Plan_Year) AS Expr1
FROM dbo.v_sc08_CD_Employee_Availabilities
GROUP BY Employee_ID, Accept_International_Assignment
I suspect this will be more efficient than the accepted answer, at scale...
;WITH x AS
(
SELECT Employee_ID, Accept_International_Assignment, Plan_Year,
rn = ROW_NUMBER() OVER (PARTITION BY Employee_ID ORDER BY Plan_Year DESC)
FROM dbo.v_sc08_CD_Employee_Availabilities -- who comes up with these names?
)
SELECT Employee_ID, Accept_International_Assignment, Plan_Year
FROM x WHERE rn = 1;
SELECT a.Employee_ID, a.Accept_International_Assignment, a.Plan_Year
FROM dbo.v_sc08_CD_Employee_Availabilities a
INNER JOIN (SELECT Employee_ID, MAX(Plan_Year) maxPlanYear
from dbo.v_sc08_CD_Employee_Availabilities
GROUP BY Employee_ID) m
ON a.Plan_Year = m.maxPlanYear AND a.Employee_ID = m.Employee_ID
I'm not sure if you want only the most recent decision and year as Raphael posted or if you want the yes's and the no's but always with the Max plan year for that employee.
Here is a query for the yes's and no's but Max plan year is always the max for the employee.
select main.Employee_ID, Accept_International_Assignment, Expr1
from (
SELECT Employee_ID, Accept_International_Assignment
FROM #v_sc08_CD_Employee_Availabilities
GROUP BY Employee_ID, Accept_International_Assignment
) main
inner join
(
select Employee_ID, MAX(Plan_Year) as Expr1
from #v_sc08_CD_Employee_Availabilities
group by Employee_ID) empPlanYear
on main.Employee_ID = empPlanYear.Employee_ID
You need a subquery on the max() and join against that.
SQL Group by & Max