SQL Query -- Student Weighted Grade Calculation - mysql

I am having trouble calculating students grades together to get their final grade.
I have the following tables
Students
----------------
stu_id
stu_fname
stu_lname
Grades
----------------
grade_id
grade_name
grade_type
grade_possible
StudentGrades
-----------------
stu_grade_id
grade_id
stu_id
grade_earned
GradeTypes
----------------
grade_type
grade_type_name
grade_weight
This is the query that I have been able to come up with
Select S.stu_fname, S.stu_lname, GT.grade_type_name,
(ROUND((SUM(SG.grade_earned)/SUM(G.grade_possible)), 2) * ROUND((GT.grade_weight/100.0)
, 2) ) as CalculatedGrade
FROM Student S
INNER JOIN StudentGrade SG on SG.stu_id = S.stu_id
INNER JOIN Grade G on SG.grade_id = G.grade_id
INNER JOIN GradeType GT WHERE G.grade_type = GT.grade_type
GROUP BY S.stu_fname, S.stu_lname, GT.grade_type_name;
I get the query report below
James | Fort | HW/QUIZ | 30.0
James | Fort | LogBook | 60.0
Robin | Hood | HW/QUIZ | 60.0
Robin | Hood | Logbook | 25.0
I want to be able to add both of James Forts grades together to get his final grade and the same for Robin Hood.
Any help is appreciated, I am stuck at this point. I am almost done. I have researched sub queries and need more help to narrow my search to get the answer.

Have you tried the following ?
SELECT results.stu_fname, results.stu_lname, sum(results.CalculatedGrade)
FROM(
SELECT S.stu_fname, S.stu_lname, GT.grade_type_name,
(ROUND((SUM(SG.grade_earned)/SUM(G.grade_possible)), 2) * ROUND((GT.grade_weight/100.0)
, 2) ) as CalculatedGrade
FROM Student S
INNER JOIN StudentGrade SG on SG.stu_id = S.stu_id
INNER JOIN Grade G on SG.grade_id = G.grade_id
INNER JOIN GradeType GT WHERE G.grade_type = GT.grade_type
GROUP BY S.stu_fname, S.stu_lname, GT.grade_type_name
)results
GROUP BY results.stu_fname, results.stu_lname;
Edit: added aliases thanks to AshReva's remark.

Well, just remove GT.grade_type_name from the select and group by. Does this do what you need?
Select S.stu_fname, S.stu_lname,
(ROUND((SUM(SG.grade_earned)/SUM(G.grade_possible)), 2) * ROUND((GT.grade_weight/100.0)
, 2) ) as CalculatedGrade
FROM Student S INNER JOIN
StudentGrade SG
on SG.stu_id = S.stu_id INNER JOIN
Grade G
on SG.grade_id = G.grade_id INNER JOIN
GradeType GT
on G.grade_type = GT.grade_type
GROUP BY S.stu_fname, S.stu_lname;

Related

difference made by sub-queries

Problem statement link
Correct code (by dongyuzhang):
select con.contest_id,
con.hacker_id,
con.name,
sum(total_submissions),
sum(total_accepted_submissions),
sum(total_views), sum(total_unique_views)
from contests con
join colleges col on con.contest_id = col.contest_id
join challenges cha on col.college_id = cha.college_id
left join
(select challenge_id, sum(total_views) as total_views, sum(total_unique_views) as total_unique_views
from view_stats group by challenge_id) vs on cha.challenge_id = vs.challenge_id
left join
(select challenge_id, sum(total_submissions) as total_submissions, sum(total_accepted_submissions) as total_accepted_submissions from submission_stats group by challenge_id) ss on cha.challenge_id = ss.challenge_id
group by con.contest_id, con.hacker_id, con.name
having sum(total_submissions)!=0 or
sum(total_accepted_submissions)!=0 or
sum(total_views)!=0 or
sum(total_unique_views)!=0
order by contest_id;
My changed code without sub-queries which is incorrect and giving larger values of sums. I don't understand how writing sub-queries is making the difference ? A simple example test case would be very helpful. THANKS !
select con.contest_id,
con.hacker_id,
con.name,
sum(total_submissions),
sum(total_accepted_submissions),
sum(total_views), sum(total_unique_views)
from contests con
join colleges col on con.contest_id = col.contest_id
join challenges cha on col.college_id = cha.college_id
left join view_stats vs
on cha.challenge_id = vs.challenge_id
left join submission_stats ss
on cha.challenge_id = ss.challenge_id
group by con.contest_id, con.hacker_id, con.name
having sum(total_submissions)!=0 or
sum(total_accepted_submissions)!=0 or
sum(total_views)!=0 or
sum(total_unique_views)!=0
order by contest_id;
In general with the subqueries first you make the aggregation before the join, so the values are right, since you have only one row per chalange_id respective contest_id and hacker id with the right sum.
If you join them together first, the values are summed up once for every matching row in the main-query.
Table1:
id | value1
a | 1
a | 2
b | 3
Table2:
id | value2
a | 5
a | 6
If you join without subqueries you got(before grouping)
a | 1 | 5
a | 1 | 6
a | 2 | 5
a | 2 | 6
So surely the sums are wrong.
select Table1.id , sum(value1), sum(value2) from
Table1 join Table2 on Table1.id = Table2.id
would return
a | 6 | 22
but
select Table1.id , sum(value1), max(sum2) from
Table1 join (select sum(value2) as sum2 from Table2 group by id) t2 on Table1.id = Table2.id
would return
a | 3 | 11
I don't know if this is the case in your query, but this is the main difference of using subqueries

Return min value from query with inner join

I have two table:
table POI:
NAME | VOTE
Paris | rt_1
Milan | rt_2
Rome | rt_3
... | ...
table rtgitems:
ITEM | TOTALRATE
rt_1 | 22
rt_2 | 3
rt_3 | 3
rt_4 | 5
... | ...
I want the attribute NAME from first table with minimum value in TOTALRATE from second table. Example: Milan, Rome.
I use this query:
SELECT POI.Name FROM POI INNER JOIN rtgitems ON POI.Vote=rtgitems.item WHERE POI.Vote = (SELECT MIN(rtgitems.totalrate) FROM rtgitems)
but don't work, I have empty result.
How must I do?
Thanks.
When ever you are using min or max kind or function in your sql you should use group by clause to get the real output from the table.
SELECT POI.Name FROM POI INNER JOIN rtgitems ON POI.Vote=rtgitems.item where totalrate= (select min(totalrate) from rtgitems)
GROUP BY POI.Name
hope it helps.
SELECT POI.Name, min(totalrate) FROM POI INNER JOIN rtgitems ON POI.Vote=rtgitems.item
GROUP BY POI.Name
try SELECT POI.name FROM POI join rtgitems ON POI.vote=rtgitems.item where totalrate<=(SELECT totalrate from rtgitems order by totalrate desc limit 1)

MySQL JOIN+COUNT+WHERE+AND

I have table of regions:
table region:
id | title
Region has many adverts:
table advert:
id | region_id | ...
Then advert has many uses (many-many through table adv_use):
table use:
use | slug | ...
----------------
1 | slug_1 | ...
2 | slug_2 | ...
..................
table adv_use:
adv_id | use_id
I want select all regions with count(*) of adverts, which have uses with slug_1 AND slug_2. If advert has no use with slug_1 or with slug_2 (or both), it's must not be counted.
What i have now:
SELECT COUNT(DISTINCT advert.id) as count
FROM region
JOIN advert ON region.id = advert.region_id
JOIN adv_use ON advert.id = adv_use.adv_id
JOIN use ON adv_use.use_id = use.id
WHERE use.slug IN ('slug_1', 'slug_2')
GROUP BY region.id
HAVING COUNT(DISTINCT adv_use.use_id) = 2
But it's working not as i want.
SQLFiddle: http://sqlfiddle.com/#!2/5b4d4/1
Thanks for help and sorry for bad english.
You need to use a subquery to select the adv_id that use both slugs:
SELECT COUNT(DISTINCT advert.id) as count, region.id as reg_id
FROM region
JOIN advert ON region.id = advert.region_id
JOIN (SELECT adv_use.adv_id
FROM adv_use
JOIN tbl_use ON adv_use.use_id = tbl_use.id
WHERE tbl_use.slug IN ('slug1', 'slug2')
GROUP BY adv_use.adv_id
HAVING COUNT(DISTINCT adv_use.use_id) = 2) adv_use
ON advert.id = adv_use.adv_id
GROUP BY region.id
;
SQLFIDDLE

Mysql query based on category

Hi i have 3 tables as follow:
business:
business_id business_name cat_id sub_cat_id
1 bz1 1 1001
2 bz2 1 1005
3 bz3 2 2001
4 bz4 1 1001
business_category:
cat_id cat_name
1 Restaurant
2 Food
3 Travel
business_sub_category:
b_sub_cat_id b_subcat_name b_maincat_id
1001 Italian 1
1002 French 1
1003 Asian 1
2001 Bagels 2
Now my query seems not work well when i want to find business based on b_subcat_name using like. This are my query:
SELECT `b`.`business_name`, `b`.`cat_id`, `b`.`business_id`, `bc`.`cat_name`, `bsc`.`b_subcat_name`, `bsc`.`b_sub_cat_id` FROM `business` AS `b` INNER JOIN `business_category` AS `bc` ON b.cat_id = bc.cat_id INNER JOIN `business_sub_category` AS `bsc` ON b.sub_cat_id = bsc.b_sub_cat_id WHERE (bc.cat_name like 'italian%') OR (bc.cat_name like '%italian') OR (bc.cat_name = 'italian')
Thanks!
I think you should using b_subcat_name in WHERE clause, because no cat_name has value contains Italy
Try to change this:
SELECT `b`.`business_name`, `b`.`cat_id`, `b`.`business_id`, `bc`.`cat_name`, `bsc`.`b_subcat_name`, `bsc`.`b_sub_cat_id` FROM `business` AS `b` INNER JOIN `business_category` AS `bc` ON b.cat_id = bc.cat_id INNER JOIN `business_sub_category` AS `bsc` ON b.sub_cat_id = bsc.b_sub_cat_id WHERE (bc.cat_name like 'italian%') OR (bc.cat_name like '%italian') OR (bc.cat_name = 'italian')
to
SELECT `b`.`business_name`, `b`.`cat_id`, `b`.`business_id`, `bc`.`cat_name`, `bsc`.`b_subcat_name`, `bsc`.`b_sub_cat_id` FROM `business` AS `b` INNER JOIN `business_category` AS `bc` ON b.cat_id = bc.cat_id INNER JOIN `business_sub_category` AS `bsc` ON b.sub_cat_id = bsc.b_sub_cat_id WHERE (bsc.b_subcat_name like 'italian%') OR (bsc.b_subcat_name like '%italian') OR (bsc.b_subcat_name = 'italian')

Update Table by Join and Group by

A Company has many Reviews which has Rating Column itself.
CompID Ratig
12 3
13 3
17 4
22 4
23 5
24 3
28 3,2
This is what I need to be set to each company by id. Now Rating In Company Column is NULL.
I've written something like this:
UPDATE Companies c
JOIN Reviews r on c.CompanyID = r.CompanyID
SET c.Rating = AVG(r.rating)
group by r.CompanyID
This should do what you want using a simple nested query, in this case probably simpler than a JOIN.
UPDATE Companies
SET Rating =
(SELECT AVG(Rating)
FROM Ratings
WHERE Companies.CompanyId = Ratings.CompId)
Simple SQLfiddle demo here.
EDIT: If you really want to use a JOIN/UPDATE FROM, it'd look something like this;
UPDATE c
SET c.Rating = r.Rating
FROM Companies c
JOIN (SELECT AVG(Rating) Rating, CompID FROM Ratings GROUP BY CompId) r
ON c.CompanyId = r.CompId
At least to me, somewhat more complicated to read, and afaik it only works on SQL Server, but here's the SQLfiddle for that too :)
UPDATE ComisionesxColaboradorxLineaPrescripciones
SET CANTIDAD_PRODUCTOS_CORE_CUMPLE = CANTIDAD
FROM #ComisionesxColaboradorxLineaPrescripciones ComisionesxColaboradorxLineaPrescripciones
INNER JOIN
(SELECT TAB_L.COD_COLAB AS COD_COLAB,TAB_L.TIPO_COLABORADOR AS TIPO_COLABORADOR, COUNT(TAB_P.COD_SEG) AS CANTIDAD
FROM #ComisionesxColaboradorxLineaPrescripciones TAB_L
INNER JOIN #ComisionesxColaboradorxLineaxProductoPrescripciones TAB_P
ON TAB_L.COD_COLAB=TAB_P.COD_COLAB AND
TAB_L.TIPO_COLABORADOR=TAB_P.TIPO_COLABORADOR
GROUP BY TAB_L.COD_COLAB,TAB_L.TIPO_COLABORADOR
) AGRUPADO
ON ComisionesxColaboradorxLineaPrescripciones.COD_COLAB = AGRUPADO.COD_COLAB AND
ComisionesxColaboradorxLineaPrescripciones.TIPO_COLABORADOR = AGRUPADO.TIPO_COLABORADOR