I have a large stats table in a Postgres DB where the schema looks like this:
player_id: integer,
region: string,
position: string,
league: string,
stats: json
I used this blog post to build the following query to find the average of a given attribute in the stats json object (using as an example the 'hits' stat):
attributes = {region: 'x', position: 'y', league: 'z'}
Stat.where(attributes).average("cast(payload ->> 'hits' as integer)").to_f
That works well and it's fast. Some of the stats, however, need to be built as a function of time the player was in game. Given a stats object with the following format:
{
"kills":10
"time_played":120 # seconds
}
I would want to get a value of 5 kills per minute (10 / (120/60)) assuming that was the only stat found (it would be much more, that's why I'm doing average, but for the sake of a simple example...)
Here I'm quite stuck. I know that sql has no trouble dividing things, but throwing in the JSON has me confused. I've tried this:
Stat.where(attributes).average("cast(payload ->> 'kills' as integer) / (cast(payload ->> 'time_played' as integer) / 60)").to_f
it returns 0 - and I'm not really sure how to debug this statement. Any ideas?
solution:
this is what ended up working, with help from EgonWilzer:
def query_for(stat, per_minute: false)
base = "cast(payload ->> '#{stat}' as float)"
return base unless per_minute
base + " / (cast(payload ->> 'time_played' as float) / 60)"
end
as realinstead ofas integer?time_playedbit by 60!) and that does seem to work - if you add it as an answer i'll happily accept it. cheers