I am stuck at some problem. The problem has two tables, namely hackers and challenges.
Here is the schema:
Hackers(hacker_id: int, name string)
Challenges(challenge_id: int, hacker_id int)
I am trying to write a query to print the hacker_id, name, and the total number of challenges created by each student. Sort your results by the total number of challenges in descending order. If more than one student created the same number of challenges, then sort the result by hacker_id. If more than one student created the same number of challenges and the count is less than the maximum number of challenges created, then exclude those students from the result.
Here is my query:
select hackers.hacker_id ,
hackers.name ,
count(challenges.challenge_id) as challenges_created
from
hackers left join challenges
on
hackers.hacker_id = challenges.hacker_id
having
count(challenges_created) >= max(challenges_created)
order by challenges_created desc, hackers.hacker_id asc
I am getting wrong output!
Please tell me where I am getting wrong!
Sample Input :
Hackers Table:image
Challengers Table :image
Sample Output:
21283 Angela 6
88255 Patrick 5
96196 Lisa 1
It's a crazy requirement to solve in mysql only. With CTE (not supported by mysql) you could reuse your query:
with tmp as (
select h.hacker_id, h.name, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id, h.name
order by challenges_created desc, h.hacker_id asc
), max_challenges_created as (
select max(challenges_created) as challenges_created
from tmp
), count_per_challenges_created as (
select challenges_created, count(1) as c
from tmp
group by challenges_created
)
select *
from tmp
cross join max_challenges_created m
left join count_per_challenges_created c on c.challenges_created = tmp.challenges_created
where tmp.challenges_created = m.challenges_created
or c.c = 1
http://rextester.com/XGYQ11641
In MySQL you can't even use a temporary table, because you couldn't use it multiple times in one query. So you have to copy&paste the same query three times (and hope that mysql will execute it only once using cache):
select *
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id
order by challenges_created desc, h.hacker_id
) tmp
cross join (
select max(challenges_created) as challenges_created
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id
order by challenges_created desc, h.hacker_id asc
) tmp
) m
left join (
select challenges_created, count(1) as c
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id
order by challenges_created desc, h.hacker_id asc
) tmp
group by challenges_created
) c on c.challenges_created = tmp.challenges_created
where tmp.challenges_created = m.challenges_created
or c.c = 1
http://rextester.com/IDUMRB49795
Try start solving smallest part of the query and keep joining them.
You can try my code which is in SQL(Oracle)
SELECT h.hacker_id,
h.name,
COUNT(c.challenge_id) AS challenge_count
FROM Hackers h
JOIN Challenges c ON c.hacker_id = h.hacker_id
GROUP BY h.hacker_id, h.name
HAVING challenge_count =
(SELECT COUNT(challenge_id) AS count_max
FROM Challenges
GROUP BY hacker_id
ORDER BY count_max DESC limit 1)
OR challenge_count IN
(SELECT DISTINCT c_compare AS c_unique
FROM (SELECT h2.hacker_id,
h2.name,
COUNT(challenge_id) AS c_compare
FROM Hackers h2
JOIN Challenges c ON c.hacker_id = h2.hacker_id
GROUP BY h2.hacker_id, h2.name) counts
GROUP BY c_compare
HAVING COUNT(c_compare) = 1)
ORDER BY challenge_count DESC, h.hacker_id;
try this it's very simple....
select
h.hacker_id,
h.name
from hackers h, difficulty d, challenges c, submissions s
where
h.hacker_id=s.hacker_id
and s.challenge_id=c.challenge_id
and d.difficulty_level=c.difficulty_level
and d.score=s.score
group by h.hacker_id, h.name
having count(*)>1
ORDER BY COUNT(*) DESC, h.hacker_id;
This is not the real answer, but the start point for you:
http://sqlfiddle.com/#!9/6910c/5
SELECT h.hacker_id ,
h.name ,
COUNT(challenges.challenge_id) as challenges_created
FROM hackers h
LEFT JOIN challenges
ON h.hacker_id = challenges.hacker_id
GROUP BY h.hacker_id
#HAVING challenges_created >= max(challenges_created)
ORDER BY challenges_created desc, h.hacker_id asc
I've commented out your HAVING clause, because can not understand what you are trying to achieve.
Explain please why do you expect only 3 rows in result? Why Rose and Frank should be excluded from the result set?
The solution is easy when you use multiple joins on the necessary tables. I like to group results as derived tabled for clarity but it can be done without those derived tables too.
select hckid, nme
from
(select h.name as nme, h.hacker_id as hckid, cnt
from (select s.hacker_id as hackerid, count(d.score) as cnt
from submissions s
join challenges c
on c.challenge_id = s.challenge_id
join difficulty d
on c.difficulty_level = d.difficulty_level
where d.score = s.score
group by s.hacker_id
having count(d.score) > 1) ft
join hackers h
on ft.hackerid = h.hacker_id) t
order by t.cnt desc, t.hckid asc
select hacker_id, name, tmp.challenges_created
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id, h.name
order by challenges_created desc, h.hacker_id
) tmp
cross join (
select max(challenges_created) as challenges_created
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id, h.name
order by challenges_created desc, h.hacker_id asc
) tmp
) m
left join (
select challenges_created, count(1) as c
from (
select h.*, count(1) as challenges_created
from hackers h
left join challenges c on c.hacker_id = h.hacker_id
group by h.hacker_id, h.name
order by challenges_created desc, h.hacker_id asc
) tmp
group by challenges_created
) c on c.challenges_created = tmp.challenges_created
where tmp.challenges_created = m.challenges_created
or c.c = 1
SELECT a.hacker_id, a.name, b.id
FROM Hackers a
INNER JOIN (SELECT hacker_id, id
FROM (SELECT hacker_id, count(challenge_id) AS id
FROM Challenges
GROUP BY hacker_id) x
WHERE id = 50
UNION ALL
SELECT hacker_id,id
FROM (SELECT hacker_id, count(challenge_id) AS id
FROM Challenges
GROUP BY hacker_id) y
WHERE id IN (SELECT id
FROM (SELECT hacker_id, count(challenge_id) AS id
FROM Challenges
GROUP BY hacker_id) x
GROUP BY id
HAVING count(*) = 1)
) b ON a.hacker_id = b.hacker_id
ORDER BY id DESC, hacker_id
This is a question in hackerranck.com you can check it here [link]
in this site you can pass answer by many sql DBMS (oracale,maysql,sqlserver, and DB2)
It's Work very well for SQL-SERVER
with t
as(
Select s.hacker_id ,
s.score,d.Difficulty_level as Difficulty_level,
c.Challenge_id
From submissions s
inner join Challenges c on c.Challenge_id = s.Challenge_id
inner join Difficulty d on d.Difficulty_level = c.Difficulty_level and d.score = s.score
)
Select t.hacker_id, h.name
From t inner join hackers h ON t.hacker_id=h.hacker_id
Where t.score in (Select score from Difficulty)
Group by t.hacker_id,h.name
Having count(t.Challenge_id) > 1
Order by count(t.Challenge_id) desc,t.hacker_id asc
I have done in SQL Server
I have joined 2 different selects , the first one uses rank to determine the ones with rank 1 and the second finds duplicates , so in the join result I filtered the result to have either 1st rank or no duplicates (cnt = 1)
select s.hacker_id, s.name, s.challenge_created from (
select * ,rank() over (order by challenge_created desc) rn from (
select h.hacker_id, name, count(challenge_id) challenge_created from hackers h
inner join challenges c on h.hacker_id = c.hacker_id
group by h.hacker_id, name) as T) as S
inner join (select A.challenge_created , count(1) cnt from (select h.hacker_id, name, count(challenge_id) challenge_created from hackers h
inner join challenges c on h.hacker_id = c.hacker_id
group by h.hacker_id, name) as A group by A.challenge_created) as O
on s.challenge_created = O.challenge_created
where rn = 1 or O.cnt = 1
order by s.challenge_created desc , hacker_id
The below query works fine in mysql
For having clause condition
I have included the record in which the count is either equal to
maximum number of challenges created OR
the number of challenges created is unique
select c.hacker_id,h.name,count(c.challenge_id) as cnt from
challenges c join hackers h
on c.hacker_id = h.hacker_id
group by c.hacker_id,h.name
having cnt =
(select max(counts) from (select count(challenge_id) as counts from challenges group by hacker_id) as countstable1) or
cnt in (select counts from (select count(challenge_id) as counts from challenges group by hacker_id) as countstable2 group by counts having count(*)=1)
order by cnt desc,c.hacker_id
Related
This query is giving wrong answer
First query:
SELECT h.hacker_id,
h.name,
COUNT(c.challenge_id)
FROM hackers h
INNER JOIN challenges c ON h.hacker_id = c.hacker_id
GROUP BY h.hacker_id,
h.name
HAVING COUNT(c.challenge_id) = (SELECT MAX(temp.cnt) AS maxi
FROM (SELECT hacker_id,
COUNT(challenge_id) AS cnt
FROM challenges
GROUP BY hacker_id) temp )
OR COUNT(c.challenge_id) IN ((SELECT temp.cnt
FROM (SELECT hacker_id,
COUNT(challenge_id) AS cnt
FROM challenges
GROUP BY hacker_id) temp
GROUP BY temp.cnt
HAVING COUNT(temp.cnt) = 1))
ORDER BY COUNT(c.challenge_id) DESC,
h.hacker_id;
This query is giving correct answer
SELECT h.hacker_id,
h.name,
COUNT(c.challenge_id) AS c_count
FROM hackers h
INNER JOIN challenges c ON h.hacker_id = c.hacker_id
GROUP BY h.hacker_id,
h.name
HAVING c_count = (SELECT MAX(temp.cnt) AS maxi
FROM (SELECT hacker_id,
COUNT(challenge_id) AS cnt
FROM challenges
GROUP BY hacker_id) temp )
OR c_count IN ((SELECT temp.cnt
FROM (SELECT hacker_id,
COUNT(challenge_id) AS cnt
FROM challenges
GROUP BY hacker_id) temp
GROUP BY temp.cnt
HAVING COUNT(temp.cnt) = 1))
ORDER BY COUNT(c.challenge_id) DESC,
h.hacker_id;
using alias I am getting correct answer.
Actually the only question is when I am using count(c.challenge_id) two times in having clause I am getting wrong answer and when I am using column alias c_count I am getting correct answer.
The HackerRank Question is here.
My code for this challenge is in MySQL:
SELECT c.hacker_id as id, h.name as name, COUNT(c.hacker_id) as cnt
FROM hackers h INNER JOIN challenges c
ON h.hacker_id = c.hacker_id
GROUP BY c.hacker_id
HAVING cnt in (
SELECT MAX(Counter1)
FROM (
SELECT COUNT(*) as Counter1
FROM challenges c1
GROUP BY c1.hacker_id
ORDER BY Counter1, c1.hacker_id
) LIMIT 1
) OR IN (
SELECT Counter2
FROM (
SELECT COUNT(*) as Counter2
FROM challenges c2
GROUP BY c2.hacker_id
HAVING Counter2=1
)
)
ORDER BY cnt DESC, id;
But the error says
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IN (
SELECT Counter2
FROM (
SELECT COUNT(*) as Counter2
' at line 13
How shall I correct my answer? How do I improve my running speed? and I am confused about the rules that when shall I give alias to subqueries table and when shall not?
Thank you!
Use a with clause and define your counts there and pass it in the having clause.
It sux.. they have a pretty low version of mysql -> see the output for "select version()"
5.7.27-0ubuntu0.18.04.1
Anyway.. if you wanna stick with MySQL you would have to repeat your "core" query multiple times :( this version does not support WITH clause .. which makes it more readable ...
/*
Enter your query here.
*/
SELECT a.hacker_id
, a.name
, a.ch_cnt as challenges_created
FROM ( -- get all challenges
SELECT h.hacker_id
, h.name
, count(c.challenge_id) as ch_cnt
FROM hackers h
LEFT JOIN challenges c
ON c.hacker_id = h.hacker_id
WHERE 1=1
GROUP BY h.hacker_id
, h.name
) a
--
LEFT JOIN ( -- tag challenges with duplicate numbers (>1)
SELECT ch_cnt
, count(*) as dupl
FROM (
SELECT h.hacker_id
, h.name
, count(c.challenge_id) as ch_cnt
FROM hackers h
LEFT JOIN challenges c
ON c.hacker_id = h.hacker_id
WHERE 1=1
GROUP BY h.hacker_id
, h.name
) bb
GROUP BY ch_cnt
HAVING count(*) > 1
) b
ON a.ch_cnt = b.ch_cnt
--
LEFT JOIN ( -- tag challenges with the max count
SELECT max(ch_cnt) ch_cnt
FROM (
SELECT h.hacker_id
, h.name
, count(c.challenge_id) as ch_cnt
FROM hackers h
LEFT JOIN challenges c
ON c.hacker_id = h.hacker_id
WHERE 1=1
GROUP BY h.hacker_id
, h.name
) cc
) c
ON a.ch_cnt = c.ch_cnt
--
WHERE 1=1
AND (
b.ch_cnt IS NULL -- remove duplicates
OR c.ch_cnt IS NOT NULL -- keep the duplicates for the max nbr of challenges
)
--
ORDER BY 3 DESC, 1 ASC
winning query: Congratulations!
Here is the question context
Julia just finished conducting a coding contest, and she needs your
help assembling the leaderboard! Write a query to print the respective
hacker_id and name of hackers who achieved full scores for more than
one challenge. Order your output in descending order by the total
number of challenges in which the hacker earned a full score. If more
than one hacker received full scores in same number of challenges,
then sort them by ascending hacker_id.
My strategy is to join all tables as a big whole table and group by the data to meet the requirement.
However I get this error from my code:
Column 'Hackers.name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
SELECT H.hacker_id, H.name
FROM Hackers H
INNER JOIN CHALLENGES C ON H.hacker_id = C.hacker_id
INNER JOIN Submissions S ON S.Challenge_id = C.Challenge_id
INNER JOIN Difficulty D ON D.difficulty_level = C.difficulty_level
WHERE S.score = D.score
AND C.difficulty_level = D.difficulty_level
-- Query can work before this line.
GROUP BY H.hacker_id
HAVING COUNT(S.submission_id) > 1
ORDER BY COUNT(S.submission_id) DESC, H.hacker_id ASC
Group by both the hacker id and name
i made this query with another join road and worked fine
SELECT h.hacker_id , h.name
FROM submissions s
INNER JOIN hackers h on h.hacker_id = s.hacker_id
INNER JOIN challenges c on c.challenge_id = s.challenge_id
INNER JOIN difficulty d on d.difficulty_level = c.difficulty_level
WHERE s.score = d.score
AND c.difficulty_level = d.difficulty_level
GROUP BY h.hacker_id ,h.name
HAVING COUNT(s.submission_id) > 1
ORDER BY COUNT(s.submission_id) DESC, h.hacker_id ASC
this problem can be solved many ways , here i solved this also executed and it worked.
step 1 : first join submissions challenges and difficulty table.
step 2 : score should be maximum. therefore, score from difficulty and submissions should be equal. and group by challenge_id , hacker_id and name this a table t
step 3: now we need name ,hacker_id so we can use table t and hackers to join. also hacker should get full score more than 1 challenges so we used having clause for that condition.
select t.hacker_id, h1.name
from(
select s.hacker_id,s.challenge_id
from submissions s join challenges c
on s.challenge_id = c.challenge_id
join difficulty d
on c.difficulty_level = d.difficulty_level
where d.score = s.score
group by s.challenge_id, s.hacker_id
)t
join hackers h1 on
t.hacker_id = h1.hacker_id
group by t.hacker_id , h1.name
having count(t.hacker_id) >1
order by count(t.hacker_id) desc, t.hacker_id
First time answering a question on stack but this is what I did
SELECT T.hacker_id, T.name FROM
(SELECT h.hacker_id,h.name, CASE
WHEN d.score = s.score then 1
ELSE 0 END AS perfect_score
FROM hackers h join submissions s on h.hacker_id = s.hacker_id
join challenges c on s.challenge_id = c.challenge_id
join difficulty d on c.difficulty_level = d.difficulty_level
WHERE
CASE WHEN d.score = s.score then 1 ELSE 0 END = 1) AS T
GROUP BY T.name, T.hacker_id
Having COUNT(*)>1
ORDER BY COUNT(*) DESC, hacker_id ASC;
below one would also work
select h.hacker_id,h.name from hackers h
left join submissions s on s.hacker_id = h.hacker_id
left join challenges c on c.challenge_id = s.challenge_id
left join difficulty d on c.difficulty_level = d.difficulty_level
where s.score = d.score
group by h.hacker_id,h.name having count(s.challenge_id) > 1
order by count(s.challenge_id) desc, h.hacker_id asc
select s.submission_id,h.hacker_id,h.name,c.difficulty_level,
row_number() over(partition by h.name,c.difficulty_level,s.score,d.score order by h.name,c.difficulty_level,s.score,d.score) as row
into #result
from submissions s
inner join hackers h on h.hacker_id = s.hacker_id
inner join challenges c on s.challenge_id = c.challenge_id --and h.hacker_id = c.hacker_id
inner join difficulty d on c.difficulty_level = d.difficulty_level
where s.score=d.score
select hacker_id,name, count(name) as success_count
into #final
from #result
--where row = 1
group by hacker_id,name
select hacker_id,name--,success_count
from #final
where success_count > 1
order by success_count desc,hacker_id
You can try this both ways for mysql
First way
select t.hacker_id,t.name FROM
(
select s.hacker_id, h.name,count(*) as total FROM Submissions s
inner join hackers h on h.hacker_id = s.hacker_id
left join challenges c on c.challenge_id = s.challenge_id
left join difficulty d on d.difficulty_level = c.difficulty_level
where s.score = d.score
group by s.hacker_id, h.name
) as t
WHERE t.total > 1
ORDER BY t.total desc, t.hacker_id
Second Way:
SELECT h.hacker_id , h.name
FROM submissions s
INNER JOIN hackers h on h.hacker_id = s.hacker_id
INNER JOIN challenges c on c.challenge_id = s.challenge_id
INNER JOIN difficulty d on d.difficulty_level = c.difficulty_level
WHERE s.score = d.score
GROUP BY h.hacker_id ,h.name
HAVING COUNT(s.submission_id) > 1
ORDER BY COUNT(s.submission_id) DESC, h.hacker_id
SELECT h.hacker_id, h.name FROM Submissions AS s JOIN Hackers AS h ON s.hacker_id = h.hacker_id JOIN Challenges AS c ON s.challenge_id = c.challenge_id JOIN Difficulty AS d ON c.difficulty_level = d.difficulty_level WHERE s.score = d.score GROUP BY h.hacker_id, h.name HAVING COUNT()>1 ORDER BY COUNT() DESC, h.hacker_id;
The following question is based on a HackerRank question here. It is written as follows:
Julia asked her students to create some coding challenges. Write a
query to print the hacker_id, name, and the total number of challenges
created by each student. Sort your results by the total number of
challenges in descending order. If more than one student created the
same number of challenges, then sort the result by hacker_id. If more
than one student created the same number of challenges and the count
is less than the maximum number of challenges created, then exclude
those students from the result.
In the challenge, I submitted the following, but for some reason there is a syntax error. What is the problem?
select h.hacker_id
, h.name
, count(c.challenge_id) count1
from hackers h
join challenges c
on c.hacker_id = h.hacker_id
where h.hacker_id not in
(select hh.hacker_id
from hackers hh
join challenges cc
on cc.hacker_id = hh.hacker_id
join
( select hhh.hacker_id
, count(ccc.challenge_id) count2
from hackers hhh
join challenges ccc
on ccc.hacker_id = hhh.hacker_id
group
by hhh.hacker_id
having count(ccc.challenge_id) <
(select max(count2)
from
( select count(cc.challenge_id) count2
from hackers hh
join challenges cc
on hh.hacker_id = cc.hacker_id
) a
) b
) t
on t.hacker_id <> hh.hacker_id
) c
group
by h.hacker_id
, h.name
order
by count(c.challenge_id)
, h.hacker_id desc
I can't comment on the validity of what follows, but it is at least syntactically valid...
select c.hacker_id
, h.name
, count(c.hacker_id) c_count
from hackers h
join challenges c
on c.hacker_id = h.hacker_id
group
by c.hacker_id
, h.name
having c_count =
( SELECT MAX(temp1.cnt)
from
( SELECT COUNT(hacker_id) cnt
from challenges
group
by hacker_id
) temp1
)
or c_count in
(select t.cnt
from
( select count(*) cnt
from challenges
group
by hacker_id
) t
group
by t.cnt
having count(t.cnt) = 1)
order
by c_count DESC
, c.hacker_id
I have tested the below two methods and they both worked fine. Just different approach to the question.
/*
Working platform:- MySQL
/
/
SELECT H.HACKER_ID,
H.NAME,
COUNT(C.CHALLENGE_ID) AS C_COUNT
FROM HACKERS H
JOIN CHALLENGES C ON C.HACKER_ID = H.HACKER_ID
GROUP BY H.HACKER_ID, H.NAME
HAVING C_COUNT =
(SELECT COUNT(C2.CHALLENGE_ID) AS C_MAX
FROM CHALLENGES AS C2
GROUP BY C2.HACKER_ID
ORDER BY C_MAX DESC LIMIT 1)
OR C_COUNT IN
(SELECT DISTINCT C_COMPARE AS C_UNIQUE
FROM (SELECT H2.HACKER_ID,
H2.NAME,
COUNT(CHALLENGE_ID) AS C_COMPARE
FROM HACKERS H2
JOIN CHALLENGES C ON C.HACKER_ID = H2.HACKER_ID
GROUP BY H2.HACKER_ID, H2.NAME) COUNTS
GROUP BY C_COMPARE
HAVING COUNT(C_COMPARE) = 1)
ORDER BY C_COUNT DESC, H.HACKER_ID;
*/
/*
The above is the original code
The following is the code I suggest
The idea is instead of looking for unique counts, you eliminate counts that are not unique
Credit: https://medium.com/jen-li-chen-in-data-science/hackerrank-sql-bd819dfcaee7
*/
SELECT c.hacker_id, h.name, count(c.challenge_id) AS cnt
FROM Hackers AS h JOIN Challenges AS c ON h.hacker_id = c.hacker_id
GROUP BY c.hacker_id, h.name
HAVING cnt = (SELECT count(c1.challenge_id) FROM Challenges AS c1 GROUP BY c1.hacker_id
ORDER BY count(*) desc limit 1) or
cnt NOT IN (SELECT count(c2.challenge_id) FROM Challenges AS c2 GROUP BY c2.hacker_id
HAVING c2.hacker_id <> c.hacker_id)
ORDER BY cnt DESC, c.hacker_id;
Write a query to print the hacker_id, name, and the total number of challenges created by each student. Sort your results by the total number of challenges in descending order. If more than one student created the same number of challenges, then sort the result by hacker_id. If more than one student created the same number of challenges and the count is less than the maximum number of challenges created, then exclude those students from the result.
I have also attached the images for the respective tables
Table Hackers:
hacker_id name
5077 Rose
21283 Angela
62743 Frank
88255 Patrick
96196 Lisa
Table Challenges:
challenge_id hacker_id
61654 5077
58302 21283
40587 88255
29477 5077
1220 21283
69514 21283
46561 62743
58077 62743
18483 88255
76766 21283
52382 5077
74467 21283
33625 96196
26053 88255
42665 62743
12859 62743
70094 21283
34599 88255
54680 88255
61881 5077
So, far I have done this
SELECT c.hacker_id, h.name, COUNT(c.challenge_id) AS challenge_count
FROM Challenges c LEFT JOIN Hackers h on c.hacker_id = h.hacker_id
GROUP by 1,c.hacker_id HAVING challenge_count >=
MAX(challenge_count) ORDER BY challenge_count DESC ,c.hacker_id DESC;
But not getting expected output. My output
I need to exclude duplicate results from output such as hackers with same number of challenges should be excluded.
There are several criteria here:
hacker_id, name, and the total number of challenges created by each student
sort your results by the total number of challenges in descending order.
If more than one student created the same number of challenges, then sort the result by hacker_id.
If more than one student created the same number of challenges then exclude those students from the result.
Except if the count equals the maximum number of challenges created,
The following deals with items 1,2, & 3...
SELECT h.*
, COUNT(c.challenge_id) challenge_count
FROM hackers h
JOIN challenges c
ON c.hacker_id = h.hacker_id
GROUP
BY h.hacker_id
ORDER
BY challenge_count DESC, hacker_id;
We can join this query to itself once, to resolve criteria 4, and again to resolve item 5, as follows:
SELECT DISTINCT a.*
FROM
( SELECT h.*
, COUNT(c.challenge_id) challenge_count
FROM hackers h
JOIN challenges c
ON c.hacker_id = h.hacker_id
GROUP
BY h.hacker_id
) a
LEFT
JOIN
( SELECT h.*
, COUNT(c.challenge_id) challenge_count
FROM hackers h
JOIN challenges c
ON c.hacker_id = h.hacker_id
GROUP
BY h.hacker_id
) b
ON b.hacker_id <> a.hacker_id AND b.challenge_count = a.challenge_count
LEFT
JOIN
( SELECT h.*
, COUNT(c.challenge_id) challenge_count
FROM hackers h
JOIN challenges c
ON c.hacker_id = h.hacker_id
GROUP
BY h.hacker_id
) c
ON c.challenge_count > a.challenge_count
WHERE b.hacker_id IS NULL
OR c.hacker_id IS NULL
ORDER
BY challenge_count DESC, hacker_id;
SELECT t1.name,
t1.hacker_id,
COALESCE(t2.challengeCount, 0) AS challengeCount
FROM Hackers t1
LEFT JOIN
(
SELECT hacker_id, COUNT(*) AS challengeCount
FROM Challenges
GROUP BY hacker_id
) t2
ON t1.hacker_id = t2.hacker_id
WHERE COALESCE(t2.challengeCount, 0) IN
(
SELECT t1.challengeCount
FROM
(
SELECT t1.hacker_id,
COALESCE(t2.challengeCount, 0) AS challengeCount
FROM Hackers t1
LEFT JOIN
(
SELECT hacker_id, COUNT(*) AS challengeCount
FROM Challenges
GROUP BY hacker_id
) t2
ON t1.hacker_id = t2.hacker_id
) t1
GROUP BY t1.challengeCount
HAVING COUNT(*) = 1
) OR COALESCE(t2.challengeCount, 0) =
(
SELECT MAX(t.challengeCount) FROM
(
SELECT COUNT(*) AS challengeCount
FROM Challenges GROUP BY hacker_id
) t
)
ORDER BY COALESCE(t2.challengeCount, 0) DESC,
t1.hacker_id