构建SQL SELECT语句以获取“前10个x”的帮助。

3
我有一个名为Points的表格:

===========================================
字段              :      类型
===========================================
id                 int(11)
user_id            int(11)
value              int(11)
type               enum('add','subtract')
timestamp          int(11)
===========================================

基本上,这个表格存储用户积分的记录。

我的问题是: 如何得到前十个总积分最高的用户?

注意: 我被告知要更改模式 -- 删除'type'字段并在'value'字段中放置正负值。 我只想知道是否可以使用当前模式实现所需的查询。

提前致谢


你可以绝对使用你的模式来完成它,无需更改。 - D'Arcy Rittich
你可以使用你的模式来完成它,但如果你按照建议做,它会更加优化。 - Nadir Sampaoli
@RedFilter 我试了biziclop的答案,它有效了!谢谢! - jgabuya
1个回答

6
我会尝试类似这样的内容:

我会尝试类似这样的方法:

SELECT
  user_id,
  SUM( IF(`type`='add',+1,-1) * `value`) AS user_points
FROM Points
GROUP BY user_id
ORDER BY SUM( IF(`type`='add',+1,-1) * `value`) DESC
LIMIT 10

看起来可行:http://sqlfiddle.com/#!2/dd207/1

另一种选择,也许更快,也许不是,诀窍是将SUM(IF())部分从内部查询中移出:

http://sqlfiddle.com/#!2/dd207/9

SELECT
  user_id,
  SUM( IF(`type`='add',+1,-1) * `valuesum`)
FROM (
      SELECT
        user_id,
        `type`,
        SUM(`value`) AS `valuesum`
      FROM     Points
      GROUP BY user_id, `type`
     ) AS p
GROUP BY p.user_id
ORDER BY SUM( IF(`type`='add',+1,-1) * `valuesum`) DESC
LIMIT 10

可能两种解决方案都需要对整个表进行全表扫描以总结所有内容,因此这种情况可能是一种明智的反规范化候选方案(例如,在另一个表中汇总每个用户的总和)。


基本思路是正确的,但你不应该在 GROUP BY 中使用 *,而且 ORDER BY 应该是 DESC - D'Arcy Rittich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接