2016-06-10 62 views
1

我陷入了一些问题。问题有两个表,即黑客和挑战。 这里是架构:MySQL:根据指定的条件排除一些结果

Hackers(hacker_id: int, name string) 
Challenges(challenge_id: int, hacker_id int) 

我想编写一个查询打印hacker_id,名称,以及每个学生带来了挑战总数。按降序排列挑战总数。如果不止一名学生创建了相同数量的挑战,则按hacker_id对结果进行排序。如果不止一名学生创造了相同数量的挑战,并且计数小于创建的最大挑战数量,则将这些学生排除在结果之外。

这里是我的查询:

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 

我得到错误的输出! 请告诉我我错了!

样品输入:

黑客表:image 挑战者表:image

Sample Output: 
21283 Angela 6 
88255 Patrick 5 
96196 Lisa 1 
+0

'> = max'没有什么意义。根据定义,max()返回集合中的最大值,所以没有其他任何值可能比这个值大。 –

+0

那么我应该如何排除那些数量大于2但小于最大值的条目(问题的最后一行) –

+1

请至少作一个一致的句子:排序*您的*结果...:它看起来像一个学生练习。 – DenisGL

回答

0

这不是真正的答案,但起点为您提供:

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 

我已将您的HAVING条款注释掉,因为无法理解您要实现的目标。

请解释为什么你期望结果只有3行?为什么RoseFrank应该从结果集中排除?

+0

这是问题陈述。可能是他们有同样数量的challenge_created,并且少于最大值。 –

0

这是一个疯狂的要求,只在mysql解决。随着CTE(不是MySQL支持的),你可以重用你的查询:

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

在MySQL中,你甚至不能使用临时表,因为你不能在一个查询中多次使用。所以,你必须复制&三次贴上相同的查询(并希望MySQL将只使用一次缓存执行):

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

0

这种方案很容易,当您使用必要的多个连接表。为了清晰起见,我喜欢将派生结果作为派生表进行分组,但是也可以在不使用派生表的情况下完成。

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