【问题标题】:MySQL nested query countingMySQL 嵌套查询计数
【发布时间】:2012-05-03 16:41:12
【问题描述】:

一些背景信息;这是一个允许用户创建挑战然后对这些挑战进行投票的应用程序(沼泽标准 userX-vs-userY 类型的应用程序)。

这里的最终目标是获得一个由 5 位用户组成的列表,按他们赢得的挑战次数排序,以创建一种排行榜。如果状态 = 已过期并且用户对该挑战的投票数超过 50(挑战在总共 100 票后过期),则用户赢得挑战。

我会在这里稍微简化一下,但本质上是三个表:

  1. 用户

    • 身份证
    • 用户名
    • ...
  2. 挑战

    • 身份证
    • issued_to
    • issued_by
    • 状态
  3. 挑战投票

    • 身份证
    • challenge_id
    • user_id
    • 投票赞成

到目前为止,我有一个内部查询,如下所示:

SELECT `challenges`.`id`
FROM `challenges_votes`
LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`)
WHERE `voted_for` = 1
WHERE `challenges`.`status` = 'expired'
GROUP BY `challenges`.`id`
HAVING COUNT(`challenges_votes`.`id`) > 50

在本例中,这将返回已过期的质询 ID,并且 ID 为 1 的用户拥有 > 50 票。

我需要做的是计算此处返回的行数,将其应用于 users 表中的每个用户,按返回的行数排序并将其限制为 5。

为此,我有以下查询:

SELECT `users`.`id`, `users`.`username`, COUNT(*) AS challenges_won
FROM (
    SELECT `challenges`.`id`
    FROM `challenges_votes`
    LEFT JOIN `challenges` ON (`challenges`.`id` = `challenges_votes`.`challenge_id`)
    WHERE `voted_for` = 1
    GROUP BY `challenges`.`id`
    HAVING COUNT(`challenges_votes`.`id`) > 0
) AS challenges_won, `users`
GROUP BY `users`.`id`
ORDER BY challenges_won
LIMIT 5

这有点到了那里,但当然这里的voted_for 用户 ID 始终为 1。这甚至是进行此类查询的正确方法吗?任何人都可以阐明我应该如何做吗?

谢谢!

【问题讨论】:

  • 您好,您能否提供有关您的表结构的更多详细信息?我以为 challenges_votes 会有 user_id,但我在您的查询中找不到它。
  • challenges_votes 中的 voted_for 列是投票对象的用户 ID,而 user_id 是投票的用户 ID(与此查询无关)。

标签: mysql


【解决方案1】:

我猜下面的脚本会解决你的问题:

-- get the number of chalenges won by each user and return top 5
SELECT usr.id, usr.username, COUNT(*) AS challenges_won
FROM users usr
JOIN (
    SELECT vot.challenge_id, vot.voted_for
    FROM challenges_votes vot
    WHERE vot.challenge_id IN (       -- is this check really necessary?
        SELECT cha.id                 -- if any user is voted 51 he wins, so
        FROM challenges cha           -- why wait another 49 votes that won't
        WHERE cha.status = 'expired'  -- change the result?
    )                                 -- 
    GROUP BY vot.challenge_id
    HAVING COUNT(*) > 50
) aux ON (aux.voted_for = usr.id)
GROUP BY usr.id, usr.username
ORDER BY achallenges_won DESC LIMIT 5;

请允许我对关闭挑战的条件提出一个小考虑:如果任何用户在 51 票后获胜,为什么还要等待另外 49 票不会改变结果?如果可以删除此约束,您将不必检查challenges 表,这可以提高查询性能——但是,它也可能会恶化,您只能在使用实际数据库进行测试后判断。

【讨论】:

  • 完美 - 谢谢!我们将开放挑战,直到它们达到 100 票总数,以便在某个时候我们可以计算用户的总票数(用户每次挑战最多可以有 100 票)。
猜你喜欢
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多