SUM位置使更高更好

时间:2013-11-23 12:50:30

标签: mysql sql activerecord ranking

我有三张桌子。变化,讨论和对话。每个讨论都有一系列对话。每次谈话都是关于改变的。然后,对话在讨论中排名1-10。你最终会得到这样的东西:

  Conversations{
    [ id: 1, discussion_id: 1, change_id 1, rank: 1 ],
    [ id: 1, discussion_id: 1, change_id 3, rank: 3 ],
    [ id: 1, discussion_id: 1, change_id 5, rank: 2 ],
    [ id: 1, discussion_id: 1, change_id 2, rank: 4 ],
    [ id: 1, discussion_id: 1, change_id 4, rank: 5 ],
    [ id: 1, discussion_id: 2, change_id 3, rank: 1 ],
    [ id: 1, discussion_id: 2, change_id 2, rank: 2 ],
    [ id: 1, discussion_id: 2, change_id 4, rank: 5 ],
    [ id: 1, discussion_id: 2, change_id 5, rank: 3 ],
    [ id: 1, discussion_id: 2, change_id 1, rank: 4 ]
  }

我想找到最高的得分变化。当我想出这个问题时,我以为我已经这样做了:

  SELECT changes.*, SUM(conversations.rank) AS score FROM "changes" 
        INNER JOIN "conversations" ON "conversations"."change_id" = "changes"."id" 
        GROUP BY changes.id

这增加了所有等级。这意味着越低越好。然而,这个相当原始的解决方案有其缺陷:如果你给一个更改排名1和3,它将得到相同的分数,就像你用4对一个变化进行排名一样。

也许要解决这个问题,你可以做得更好更好:第一名= 5分,第二名= 4分,等等。我不知道如何实现这一点。它也可能不是最好的方法。

Here你可以找到一个上下文的SQL小提琴。仅仅是一个FYI:我正在以积极的记录这样做。我用这个生成了查询:

Change.select("changes.*, SUM(conversations.rank) as conversations_rank").group("changes.id").joins(:conversations)

1 个答案:

答案 0 :(得分:0)

我想出了两种方法。两者都很简单。我只是有点傻了:)

第一个,也可能是最简单的一个:

SELECT changes.name, SUM(11 - conversations.rank) as score FROM "changes" 
      INNER JOIN "conversations" 
        ON "conversations"."change_id" = "changes"."id" 
      GROUP BY changes.id 
      ORDER BY score desc

简单的数学呃。因此,如果conversations.rank = 1,那么它将是10,因为1减11是10。

或许更好的方法是使用另一张表:

CREATE TABLE ranks (
  rank INT UNSIGNED PRIMARY KEY, 
  value INT UNSIGNED
);

INSERT INTO ranks 
       VALUES (1, 5),
              (2, 4),
              (3, 3),
              (4, 2),
              (5, 1);

然后在conversations.rank上进行联接排名:

SELECT changes.name, SUM(ranks.value) as score FROM "changes"
      INNER JOIN "conversations"
        ON conversations.change_id = changes.id
      INNER JOIN "ranks"
        ON conversations.rank = r.rank
      GROUP BY changes.name;

感谢您的帮助。