MYSQL Sum results of a calculation - mysql

I am building a query in mysql 5.0 to calculate a student semester grade. The initial table (studentItemGrades) contains the list of assignments etc which will be used to calculate the final grade. Each assignment has a PossibleScore, Grade and Weight. The calculation should group all similarly weighted items, and provide the SUM(GRADE)/SUM(POSSIBLESCORE) based on a date range of when the assignment was due. The problem I am encountering is the final summation of all the individual weighted grades. For example, the results currently produce the following:
CourseScheduleID sDBID AssignedDate DueDate Weight WeightedGrade
1 519 2010-08-26 2010-08-30 10 0.0783333333333333
1 519 2010-09-01 2010-09-03 20 0.176
1 519 2010-09-01 2010-09-10 70 0.574
from the query:
SELECT CourseScheduleID, sDBID, AssignedDate, DueDate, Weight,
((SUM(Grade)/SUM(PossibleScore))*(Weight/100)) AS WeightedGrade
FROM studentItemGrades
WHERE DueDate>='2010-08-23'
AND DueDate<='2010-09-10'
AND CourseScheduleID=1
AND sDBID=519
AND Status>0
GROUP BY Weight
The question: How do I now SUM the three results in the WeighedGrade output? And by the way, this is part of a much larger query for calculating all grades for all courses on a particular campus.
Thanks in advance for your help.

You can use a subquery, like so:
SELECT SUM(WeightedGrade) FROM
(
SELECT CourseScheduleID, sDBID, AssignedDate, DueDate, Weight,
((SUM(Grade)/SUM(PossibleScore))*(Weight/100)) AS WeightedGrade
FROM studentItemGrades
WHERE DueDate>='2010-08-23'
AND DueDate<='2010-09-10'
AND CourseScheduleID=1
AND sDBID=519
AND Status>0
GROUP BY Weight
) t1

In order to sum the three results, you would need to requery the results of this select using another select with a group by. This could be done using a single sql statement by using subqueries.
SELECT sq.CourseScheduleID, sq.sDBID, SUM(sq.WeightedGrade) as FinalGrade
FROM
(
SELECT CourseScheduleID, sDBID, AssignedDate, DueDate, Weight,
((SUM(Grade)/SUM (PossibleScore))*(Weight/100)) AS WeightedGrade
FROM studentItemGrades WHERE DueDate>='2010-08-23' AND DueDate<='2010-09-10'
AND CourseScheduleID=1 AND sDBID=519 AND Status>0 GROUP BY Weight
) AS sq
GROUP BY sq.CourseScheduleID, sq.sDBID

Related

Sum Distinct Duplicated Values

I have a dataset as below:
customer buy profit
a laptop 350
a mobile 350
b laptop case 50
c laptop 200
c mouse 200
It does not matter how many rows the customer has, the profit is already stated in the row (it's already an accumulative sum). For example, the profit of customer a is 350 and the profit of customer c is 200.
I would like to sum uniquely the profit for all the customers so the desire output should be 350 + 50 + 200 = 600. However, I need to execute this in one line of code (without doing subquery, nested query or write in a separate CTE).
I tried with Partition By but cannot combine MAX and SUM together. I also tried SUM (DISTINCT) but it does not work either
MAX(profit) OVER (PARTITION BY customer)
If anyone could give me a hint on an approach to tackle this, it would be highly appreciated.
You really should use a subquery here:
SELECT SUM(profit) AS total_profit
FROM (SELECT DISTINCT customer, profit FROM yourTable) t;
By the way, your table design should probably change such that you are not storing the redundant profit per customer across many different records.
You can combine SUM() window function with MAX() aggregate function:
SELECT DISTINCT SUM(MAX(profit)) OVER () total
FROM tablename
GROUP BY customer;
See the demo.
Select sum(distinct profit) as sum from Table
You can select max profit of each customer like this:
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
Then you can summarise the result in your code or even in the query as nested queries:
SELECT SUM(max_profit) FROM (
SELECT customer, MAX(profit) AS max_profit
FROM tablename
GROUP BY customer
) AS temptable

How to select a GROUPED BY average for a non-specific key in the SELECT statement

I am looking for a way to select the average for a particular user in the select statement and then calculate the variance in the current row from the previously calculated average.
The User and Attmept_Number is a composite key. In addition this should be done in either the SELECT or WHERE clause. I know of a solution using FROM (SELECT...), but in this instance I am looking for a different solution.
SELECT
User,
Attmept_Number,
(User_Score - AVG(User_Score)) As Variance
FROM Scores
With the above statement, I am getting the column average, not the average for the user. When I add a GROUP BY clause it causes issues due to the Composite key.
Result:
User Score Variance
1 5 -6
1 10 -1
1 15 4
3 14 3
Goal:
User Score Variance
1 5 -5
1 10 0
1 15 5
3 14 0
With MySQL 8.0, it's as simple as using window function AVG(...) OVER(...):
SELECT
user,
score,
score - AVG(score) OVER(PARTITION BY user) AS variance
FROM scores
In earlier versions, you can use an aggregate subquery to compute the average per user and then JOIN it with the table:
SELECT
s.user,
s.score,
s.score - t.avg_score AS variance
FROM scores s
INNER JOIN (
SELECT user, AVG(score) avg_score FROM scores GROUP BY user
) t ON s.user = t.user

Finding average highest salary

Write a query to find the highest average sales among all the salespersons using the given table.
Table: Sales
Field Type
InvoiceNo Integer
SalesPerson Text
TotalSale Integer
Sample
InvoiceNo SalesPerson TotalSale
1 Acheson 50
2 Bryant 25
3 Bennett 250
4 Acheson 50
5 Bryant 100
6 Bennett 250
Sample output
max(totalsale)
250.0000
I tried using: SELECT MAX(TotalSale) FROM Sales. My output for sample test case was 250 but it was given wrong answer verdict in an online judge.
Also, when I changed the query to : SELECT MAX(TotalSale*1.0000) FROM Sales,I got correct answer for sample test case but still wrong answer for other test cases.
What is meant by average here? What should be the query?
Also, this isn't from any on-going competition. It is from a practice test which you can attempt here: https://www.hackerearth.com/challenge/test/kredx-data-analyst-test/
1.First you have to calculate the average TotalSale for each SalesPerson using the AVG function.
SELECT SalesPerson, AVG(TotalSale) AS 'TotalSale'
FROM Sales
GROUP BY SalesPerson
2.Find out the max value from the table generated by the above query.
SELECT MAX(avgSales.TotalSale)
FROM (SELECT AVG(TotalSale) AS 'TotalSale' FROM Sales GROUP BY SalesPerson) AS avgSales
SELECT avg(TotalSale) as MaxTotal
FROM Sales
GROUP BY Salesperson
ORDER BY MaxTotal desc
LIMIT 1
Output:
MaxtTotal
250.0000
The average sale would use the avg() function:
select salesperson, avg(totalsale) as avg_totalsale
from sales
group by salesperson;
The maximum of the average can be obtained using order by and limit:
select avg(totalsale) as avg_totalsale
from sales
group by salesperson
order by avg_totalsale desc
limit 1;
Here is another way to answer this:
select avg(TotalSale)
from Sales
group by SalesPerson
order by totalSale desc limit 1;
output:
avg(TotalSale)
250.0000
Minor change to #gordon-linoff 's answer to pass the sample test case.
select CAST(avg(totalsale) AS DECIMAL(16,4)) as avg_totalsale
from sales
group by salesperson
order by avg_totalsale desc
limit 1;
CAST(avg(totalsale) AS DECIMAL(16,4))
The above part will restrict the zero's in decimal place up to 4. Convert 250.00000000 to 250.0000
SELECT max(avgsale.TotalSale)
FROM (Select Cast(Round(Avg(TotalSale),2) as dec(10,4)) 'TotalSale' from Sales
GROUP BY salesPerson) avgsale

SQL query for selecting maximum from 2 different columns

I got a question in my homework for SQL about selecting the maximum values from the same table that have different class "Letters"
For example:
ID Student Group Avg(value)
-------------------------------------
1 stud1 A 9
2 stud2 A 9.5
3 stud3 B 8
4 stud4 B 8.5
What my query should do, is to show stud2 and stud4.The maximum from their respective groups.
I managed to do it in the end, but it took a lot of characters so I thought that maybe there's a shorter way to do. Any ideas? I used to first search the id or the stud that has max avg(value) from group A, intersecting with the id of the stud that has max avg(value) from B and then putting everything into one big select and then using those intersected IDs into another query that requested to show some different things about those IDs. But as I said, it looked far too long and thought that maybe there's an shorter way.
Try this (I renamed group to grp and avg to avg_val as those are reserved keywords):
select t1.*
from your_table t1
inner join (
select grp, max(avg_val) avg_val
from your_table
group by grp
) t2 on t1.grp = t2.grp
and t1.avg_val = t2.avg_val;
It finds maximum avg value per group and joins it with original table to get the corresponding students.
Please note that if there are multiple students with same avg as the max value of the that group, all of those students will be returned.

Avg value using subquery

I want to make a query that gives me the max and min average mark of students. I can get the max and min marks, but I don't know how to caluclate average of those.
SELECT MAX(mark) AS Max_mark FROM passed
GROUP BY student_id;
This gives the max mark from every student, I need average of that values.
Use AVG to get the avarage per student. Use MIN and MAX on this to get the highest and lowest avararage over all students.
select
min(avg_mark) as min_avg_mark,
max(avg_mark) as max_avg_mark
from
(
select avg(mark) as avg_mark
from passed
group by student_id
) as avg_marks;
SELECT student_id, (MAX(mark) + MIN(mark)) / 2 AS Avg_mark FROM passed
GROUP BY student_id;
Or are you looking for average
SELECT student_id, AVG(mark) as Avg_mark FROM passed
GROUP BY student_id;