Question

Let's say that have a table called bets. I want to run an aggregate sql query that counts rows satisfying certain conditions. For example, I want to return a count of all bets won, all bets lost, etc. I also want these counts to be grouped by several different columns. I tried a few different queries, but not getting the results I'd expect. For example:

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')

Just gives me the result of "1" for bets_won or bets_lost or bets_pushed for any of the records returned. Using Rails 3.2 + postgres.

Was it helpful?

Solution

you have to pass case expression so it will return bigint value .

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')

OTHER TIPS

count(expression) is defined to count the "number of input rows for which the value of expression is not null". The state = 'won' expression only evaluates to NULL only when state is null, otherwise it will be one of the boolean values TRUE or FALSE. The result is that count(state = 'won') is actually counting the number of rows where state is not null and that's not what you're trying to do.

You can use Paritosh Piplewar's solution. Another common approach is to use sum and case:

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top