Wrong output in MYSQL - mysql

I have a question as follows:
The total score of a hacker is the sum of their maximum scores for all of the challenges. Write a query to print the hacker_id, name, and total score of the hackers ordered by the descending score.
If more than one hacker achieved the same total score, then sort the result by ascending hacker_id.
Exclude all hackers with a total score of 0 from your result.
The 2 tables are given as follows:
table: Hackers
========================================
hacker_id: Integer (ID of the hacker)
name: String (Name of the hacker)
========================================
table: Submissions
===================================================
submission_id: Integer (ID of the submission)
hacker_id: Integer (ID of the hacker)
challenge_id: Integer (ID of the challenge)
score: Integer (score of the submission)
===================================================
The MYSQL query I've written is as follows:-
select
a.hacker_id,
a.name,
a.total
from(
select
h.hacker_id,
h.name,
sum(case when s.hacker_id=h.hacker_id then s.score else 0 end) as total
from
hackers h,
submissions s
group by
h.hacker_id,
h.name
) as a
where
a.total>0
order by
a.total desc,
a.hacker_id asc;
I'm getting wrong output for this though that output satisfies all the rules of order & ommission of 0 scorers as required. I'm very confused as to what the error is. Someone please help!!!

Something like:
select h.hacker_id, h.name, sum(s.score) as total
from hackers h
join submissions s using (hacker_id)
group by h.hacker_id
order by sum(s.score) desc, h.name
having sum(s.score) > 0
The basic idea is that to start with we join hackers and submissions tables together, and then sum the score and use the group by clause to get a new total for each hacker. Then add the order by. Then finally the HAVING is what filters out anyone with a zero score.
I don't have your data set to test with but hopefully this is close enough that it will help you along the way!

The total score of a hacker is the sum of their maximum scores for all of the challenges.
First, you need to find the maximum score a hacker, for each challenge:
SELECT hacker_id
, challenge_id
, MAX(score) AS max_score
FROM Submissions
GROUP BY hacker_id
, challenge_id
Then you need to sum that for each hacker:
SELECT hacker_id
, SUM(max_score) AS total_score
FROM ( SELECT hacker_id
, challenge_id
, MAX(score) AS max_score
FROM Submissions
GROUP BY hacker_id
, challenge_id
) ms
GROUP BY hacker_id
Finally you apply the rest:
Exclude all hackers with a total score of 0 from your result.
Print the hacker_id, name, and total score
Ordered by the descending score, then by ascending hacker_id.
SELECT hacker_id
, ( SELECT name
FROM Hackers h
WHERE h.hacker_id = ms.hacker_id
) AS name
, SUM(max_score) AS total_score
FROM ( SELECT hacker_id
, challenge_id
, MAX(score) AS max_score
FROM Submissions
GROUP BY hacker_id
, challenge_id
) ms
GROUP BY hacker_id
HAVING SUM(max_score) <> 0
ORDER BY total_score DESC
, hacker_id

Related

how to find index ( id ) of generic column in mysql

I have a table with name rating as this.
I am writing the query like this
SELECT user_id, sum(score) as score
FROM quiz_rashad.rating
group by user_id
order by score desc
then how I get rating index of the 12th user?
Thank you for helping.
Assuming, that "the 12th user" means the user with the ID 12:
In MySQL 8.0+ you can use dense_rank().
SELECT x.rating_index
FROM (SELECT r.user_id,
dense_rank() OVER (ORDER BY sum(r.score) DESC) rating_index
FROM quiz_rashad.rating r
GROUP BY r.user_id) x
WHERE x.user_id = 12;
Edit:
For MySQL 5.7 you have to use subqueries getting the distinct count of total scores greater than or equal the total score for the user with ID 12.
SELECT count(DISTINCT x.score) rating_index
FROM (SELECT r.user_id,
sum(r.score) score
FROM quiz_rashad.rating r
GROUP BY r.user_id) x
WHERE x.score >= (SELECT sum(r.score)
FROM quiz_rashad.rating r
WHERE r.user_id = 12)
We can try using LIMIT with OFFSET here:
SELECT user_id, SUM(score) AS score
FROM quiz_rashad.rating
GROUP BY user_id
ORDER BY score DESC
LIMIT 1 OFFSET 11;
This answer assumes that what you really want here is the record with the twelfth rank. It also assumes that no two users would be tied for the same score.

15 days of Sql From hackerrank

I am unable to understand the use of this line in a code can someone please explain me about this or give some different way to approach to this question
Link to the question:https://www.hackerrank.com/challenges/15-days-of-learning-sql
Code:
select
submission_date ,
( SELECT COUNT(distinct hacker_id)
FROM Submissions s2
WHERE s2.submission_date = s1.submission_date
AND ( SELECT COUNT(distinct s3.submission_date)
FROM Submissions s3
WHERE
s3.hacker_id = s2.hacker_id
AND s3.submission_date < s1.submission_date
) = dateDIFF(s1.submission_date , '2016-03-01'))
, ( select hacker_id
from submissions s2
where s2.submission_date = s1.submission_date
group by hacker_id
order by count(submission_id) desc , hacker_id limit 1
) as shit
, ( select name
from hackers where hacker_id = shit
)
FROM
( select distinct submission_date
from submissions) s1
group by submission_date
Unable to understand why they have used this line from this part of the code:
(s3.submission_date < s1.submission_date) = dateDIFF(s1.submission_date , '2016-03-01'))
CREATE TABLE #max_submissions (
submission_date date,
hacker_id integer,
submission_count integer,
ordering_row integer
)
insert into #max_submissions
select
submission_date,
hacker_id,
submission_count,
row_number() over(partition by submission_date order by submission_count desc, hacker_id) as ordering_row
from (
select submission_date,
hacker_id,
count(hacker_id) as submission_count
from submissions
group by submission_date, hacker_id
) tbl_submission_count
CREATE TABLE #hacker_counts (
submission_date date,
hacker_count integer
)
insert into #hacker_counts
select tbl.submission_date,
COUNT(distinct tbl.hacker_id) as cc
from (
select *,
(case when (
(select count(*)
from (select distinct *
from (select s1.hacker_id,
s1.submission_date
from Submissions s1
where s1.hacker_id = s.hacker_id and
(s1.submission_date >= '2016-03-01' and
s1.submission_date <= s.submission_date)) t1
) t2
) >= (DATEDIFF(day, '2016-03-01', s.submission_date) + 1) )
then 1
else 0
end) as logic
from Submissions s
) tbl
where tbl.logic = 1
group by tbl.submission_date
select max_submissions.submission_date,
hacker_counts.hacker_count,
max_submissions.hacker_id,
h.name
from #max_submissions max_submissions
inner join hackers h on max_submissions.hacker_id = h.hacker_id
left join #hacker_counts hacker_counts on max_submissions.submission_date = hacker_counts.submission_date
where max_submissions.ordering_row = 1
order by max_submissions.submission_date
drop table #max_submissions
drop table #hacker_counts
To understand this line
( SELECT COUNT(distinct s3.submission_date)
FROM Submissions s3
WHERE
s3.hacker_id = s2.hacker_id
AND s3.submission_date < s1.submission_date)
= dateDIFF(s1.submission_date , '2016-03-01')
First understand left hand side:
(SELECT COUNT(distinct s3.submission_date) FROM Submissions s3 WHERE s3.hacker_id = s2.hacker_id AND s3.submission_date < s1.submission_date)
This line counts the unique submission dates for each hacker_id uptil the current date,
So if the date for one row is 2016-03-05, it will count unique submissions for a hacker_id uptil this date (note it will count multiple submissions by a single hacker on a day as 1 count only)
In other words, this takes a hacker_id and start checking if there is a submission by this hacker_id for each day from 1st day uptil this day,it will do this for each submission date
Then Understand Right Hand Side:
dateDIFF(s1.submission_date , '2016-03-01')
this will take the difference of this current date 2016-03-05 to first day 2016-03-01,
Understanding the whole statement now:
So if a hacker made at least one submission each day from 2016-03-05 to 2016-03-01, then both sides of the above code will be equal,
that is date difference from 5th to 1st will be 5 (Right Hand Side) and distinct submission date for a hacker who made at least one submission each day from 1st to 5th will also be 5 (left hand side)

How to get rank and max score where each user has many scores in Mysql?

I have a Score table that hold user_id,score in MySql . each user has many scores . I want to get best rank of each user ?
I check a lot of solution but all of them work for table that each user has single score .
I tried this but sometimes user by min score got higher rank :
SET #rank= 0;;
SELECT Users.username, score, rank
FROM (
SELECT * , #rank := #rank +1 AS rank
FROM Scores
JOIN (
SELECT userid AS user_id2, MAX( score ) AS max_score
FROM Scores
GROUP BY user_id2
ORDER BY max_score DESC
) AS max_score_table ON max_score = Scores.score
AND Scores.userid = user_id2
) derived_table
join Users On (Users.id=derived_table.user_id2)
ORDER BY rank
LIMIT 0, 100

Find student with the maximum average mark

i have tried a lot without success, i want to display only the maximum average of student marks from the list of student as shown on the table below.
My table
i want to get the result as below
expected output
what i have done so far
SELECT MAX(a.Total_Qty) As TotalMax,a.studentId
FROM(
SELECT AVG( s.marks ) AS Total_Qty,s.studentId
FROM results s
WHERE s.stream = 'Form One'
GROUP BY s.studentId) AS a
Inner query will give you the list of averages for each student.
Then we order (descending) by their average score and finally we get the top 1 (Limit 1)
SELECT a.studentId, a.Total_Qty as MaxAvg
FROM(
SELECT AVG( s.marks ) AS Total_Qty,s.studentId
FROM results s
WHERE s.stream = 'Form One'
GROUP BY s.studentId)
AS a
Order by a.Total_Qty Desc
Limit 1
Alternatively:
SELECT AVG( s.marks ) AS Total_Qty,s.studentId
FROM results s
WHERE s.stream = 'Form One'
GROUP BY s.studentId
Order By AVG( s.marks ) Desc
Limit 1
(UNTESTED) I hope it helps
if you are using MSSQL :
SELECT TOP(1) studentId, AVG(marks) FROM results GROUP BY studentId
ORDER BY MAX(AVG(marks)) Desc
if you are using SQL :
SELECT studentId, AVG(marks) FROM results GROUP BY studentId
ORDER BY MAX(AVG(marks)) Desc Limit 0,1

MYSQL GROUP BY MAX score

I have a table called scores which contains columns
How do I select which id_team is top scorer per game
i m trying with this, but that's not correct result
SELECT MAX( score ) , id_team
FROM scores
GROUP BY `id_game`
LIMIT 0 , 30
You can use a self join to find out the right team id for game a which has max score
SELECT s.*
FROM scores s
JOIN (
SELECT MAX(score) score, id_game
FROM scores
GROUP BY id_game ) ss USING(score ,id_game )
LIMIT 0 , 30
select A.id_game, A.id_team as winning_team
from scores A,
(
select max(score) as max, id_game
from scores
group by id_game
)B
where A.id_game = B.id_game
and A.score = B.max