Rails聚合查询计数满足特定条件的行

时间:2014-05-03 00:15:34

标签: sql ruby-on-rails postgresql aggregate-functions

让我们说有一张名为赌注的牌桌。我想运行一个聚合的SQL查询来计算满足某些条件的行。例如,我想返回赢得的所有赌注,所有赌注丢失等的计数。我还希望这些计数按几个不同的列分组。我尝试了几个不同的查询,但没有得到我期望的结果。例如:

Bet.select("user_id, event_id, bet_line_id, pick, COUNT(state = 'won') AS bets_won,
COUNT(state = 'lost') AS bets_lost, COUNT(state = 'pushed') AS bets_pushed").
group('user_id, event_id, bet_line_id, pick')

给我结果" 1"对于返回的任何记录的bets_won或bets_lost或bets_pushed。使用Rails 3.2 + postgres。

2 个答案:

答案 0 :(得分:2)

您必须传递case表达式,以便返回bigint值。

Bet.select("user_id, event_id, bet_line_id, pick, 
  COUNT(CASE WHEN state = 'won' then 1 ELSE null END) AS bets_won,
  COUNT(CASE WHEN state = 'lost' then 1 ELSE null END) AS bets_lost, 
  COUNT(CASE WHEN state = 'pushed' then 1 ELSE null END) AS bets_pushed").
 group('user_id, event_id, bet_line_id, pick')

答案 1 :(得分:2)

count(expression)被定义为计算"number of input rows for which the value of expression is not null"state = 'won'表达式仅在state is null时才计算为NULL,否则它将是布尔值TRUE或FALSE之一。结果是,count(state = 'won')实际上是在计算state is not null的行数,而不是您尝试做的行。

您可以使用Paritosh Piplewar's solution。另一种常见方法是使用sumcase

sum(case state when 'won'    then 1 else 0 end) as bets_won,
sum(case state when 'lost'   then 1 else 0 end) as bets_lost,
sum(case state when 'pushed' then 1 else 0 end) as bets_pushed