SQL Group By和Order By with Aggregate Functions

时间:2012-03-15 01:37:43

标签: sql ruby-on-rails ruby

我正在整理一个Rails应用程序,我遇到了一些SQL障碍。虽然它可以在Sqlite3中解决,但当我将它移动到运行Postgres的Heroku服务器时,它会窒息死亡。情况如下:

SPORTS
-----------------------------
|   id    |      title      |
-----------------------------
|   1     |  Baseball       |
-----------------------------

SPORTS_VOTE
------------------------------------
|  id  |   sport_id    |    vote   |
------------------------------------
|  1   |       1       |     1     |
------------------------------------

投票栏可以是1或-1。我想得到一份按总票数排序的运动清单。我在Sqlite3中使用的查询是这样的:

  SELECT s.title, sum(sv.vote)
    FROM sports s 
   INNER JOIN sports_vote sv ON s.id = sv.sport_id 
 GROUP BY s.id
 ORDER BY sum(sv.vote);

在任何可敬的数据库中,此查询都会抱怨聚合函数等。执行此操作的最佳方法是什么?我最好在体育表中保留一个“投票”字段,并在投票时更新此字段吗? Sports_Vote表还记录了提交投票的用户的ID,因此需要它。

其次,我想理想地将两个相似的表组合在一起,这样我就能得到一个很好的名单,运动和饼干按照投票的降序排列(曲棍球排名第一,枫树饼干#2,足球#3等等) )。有什么建议吗?

1 个答案:

答案 0 :(得分:4)

使用group by时防止错误的经验法则是:

  • 所有未汇总的列都必须包含在group by子句中。

因此,您的查询应为:

 SELECT s.id, s.title, sum(sv.vote)
    FROM sports s 
   INNER JOIN sports_vote sv ON s.id = sv.sport_id 
 GROUP BY s.id, s.title
 ORDER BY sum(sv.vote);

OR

 SELECT s.title, sum(sv.vote)
    FROM sports s 
   INNER JOIN sports_vote sv ON s.id = sv.sport_id 
 GROUP BY s.title
 ORDER BY sum(sv.vote);

要与第二个表和排名结合使用,您只需使用unionorder by将适用于合并后的结果):

 SELECT s.title, sum(sv.vote) vote_count
    FROM sports s 
   INNER JOIN sports_vote sv ON s.id = sv.sport_id 
 GROUP BY s.title
 UNION   
 SELECT s.title, sum(sv.vote) vote_count
    FROM cookies s 
   INNER JOIN cookies_vote sv ON s.id = sv.sport_id 
 GROUP BY s.title
 ORDER BY vote_count DESC;

关于你是否应该在体育表中保留投票数并在每次投票时更新的问题,这取决于你的问题。这样做会在生成上述报告时提供更好的性能(因为不再需要group byinner join),但会降低投票的性能(从现在开始)你必须插入和更新第二个表)。所以这取决于你的优先事项。