MySQL:根据指定条件排除某些结果

时间:2016-06-10 21:23:27

标签: 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  

10 个答案:

答案 0 :(得分:1)

这只是在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

答案 1 :(得分:1)

尝试开始解决查询的最小部分并继续加入它们。 您可以尝试我的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;

答案 2 :(得分:1)

尝试一下,这很简单。...

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;

答案 3 :(得分: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

答案 4 :(得分:0)

在必要的表上使用多个连接时,解决方案很容易。为了清楚起见,我喜欢将结果分组为派生表,但也可以在没有这些派生表的情况下完成。

prod

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这是hackerranck.com中的问题,您可以检查它here [link] 在此站点中,您可以通过许多SQL DBMS(oracale,maysql,sqlserver和DB2)传递答案

对于 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

答案 8 :(得分:0)

我已经在SQL Server中完成 我加入了2个不同的选择,第一个使用等级来确定具有等级1的选择,第二个使用重复的选择,因此在联接结果中,我将结果过滤为具有第一个等级或没有重复(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

答案 9 :(得分:0)

以下查询在mysql中工作正常 对于具有条款条件 我已经包含了计数等于 创建的最大挑战数或 挑战的数量是独一无二的

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