找到一种方法来加入有限数量的行

时间:2014-02-25 21:05:17

标签: mysql

我已经为我想要运行的查询提出了以下理论解决方案:

SELECT m.id, u.user_id, COUNT(u.user_id) FROM matches m
JOIN (
    SELECT * FROM match_user u1 WHERE user_id IN (
        SELECT user_id FROM match_user WHERE match_id = u1.match_id ORDER BY created_at LIMIT 10
    )
) u ON u.match_id = m.id
GROUP BY u.user_id 
ORDER BY COUNT(u.user_id)

然而,MySQL“还没有支持'LIMIT& IN / ALL / ANY / SOME子查询'”,因为它告诉我。

我想要实现只有match_user中最早的10个条目加入matches。怎么做到这一点?

带有虚拟数据的表转储:http://ge.tt/20zOdpL1/v/0

修改

Per Strawberry的建议我尝试了SQL Fiddle并输入了我正在使用的虚拟数据:http://sqlfiddle.com/#!2/7a3e9

查询所需的输出包含两列:user_idnumber_of_matches

number_of_matchesuser_id通过match_user表与匹配相关联的次数。

到目前为止一切顺利:

SELECT u.user_id, COUNT(u.user_id)
FROM matches m
JOIN match_user u ON u.match_id = m.id
GROUP BY u.user_id 

抓住的是每场比赛只允许10名球员排队。对于我粘贴到SQL Fiddle的数据,我们将使用3的限制,因为10的虚拟数据不够。

所以我想限制连接表,以确保每次匹配时,我们只获取match_user中最早的3个条目。

这意味着首先回复(user_id)的3名玩家(created_at)正在玩。

参考SQL小提琴,应该忽略match_userid = 5的行,因为这是唯一一个RSVP超过3个用户的情况,并且这是match_id = 2

最早的RSVP

进一步限制

如果我们每场比赛限制为2名玩家,则会从输出中排除另外两行。行id = 4且id = 7,因为它们是match_id中最早的行。

1 个答案:

答案 0 :(得分:0)

我假设您需要匹配列表(如评论中所示),而不是原始问题中建议的user_id某种计数。在任何情况下,您都可以将聚合添加到以下查询中,如果这是您真正想要的。

此查询使用where子句为每个matchid最多获取10个用户ID。我们的想法是使用较小的match_id计算用户数,并将此数字与10进行比较:

select mu.match_id, mu.user_id
from match_user mu join
     matches m
     on mu.match_id = m.id
where 10 >= (select count(*)
             from match_user mu2 join
                  matches m2
                  on mu2.match_id = m2.id
             where mu2.match_id = mu.match_id and
                   mu2.created_at <= mu.created_at
            );

编辑:

以下查询按用户执行摘要:

select mu.user_id, count(*)
from match_user mu join
     matches m
     on mu.match_id = m.id
where 10 >= (select count(*)
             from match_user mu2 join
                  matches m2
                  on mu2.match_id = m2.id
             where mu2.match_id = mu.match_id and
                   mu2.created_at <= mu.created_at
            )
group by mu.user_id;

SQL小提琴是here

编辑II:

这是如何工作的?显然,查询的有趣部分是where子句中的子查询。此子查询计算的match_user记录的数量小于created_at日期,而不是外部查询中的给定记录。您可以将其视为“循环”,尽管实现不一定是嵌套循环。

子查询中的where子句是子查询的关键部分。第一个子句查看具有相同match_id的所有记录。第二部分仅匹配早期的created_at记录。 count(*)计算数字,外部过滤器仅在最多10个此类记录时才保留特定记录。

当我查看查询时,我意识到子查询中的连接不是必需的,也不是外部查询中的连接。这应该产生相同的结果:

select mu.user_id, count(*)
from match_user mu
where 10 >= (select count(*)
             from match_user mu2
             where mu2.match_id = mu.match_id and
                   mu2.created_at <= mu.created_at
            )
group by mu.user_id;