2016-06-10 106 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