Rails Query - Sum Results - ruby-on-rails

Score.where(period: ["q1", "q2"]).pluck(:game_id, :home_score, :away_score)
This query returns results like this:
[[57927, 26, 19], [57927, 28, 23],
[57928, 12, 21], [57928, 17, 25],
[57929, 28, 15], [57929, 24, 20]]
How can I sum the :home_score and :away_score results of the same :game_id, to get this
[[57927, 54, 42],
[57928, 29, 46],
[57929, 52, 35]]

Assuming game_id is a foreign key mapping to Game object, try:
Game.joins(:scores).select("#{Game.table_name}.id, SUM(#{Game.table_name}.home_score) AS home_total, SUM(#{Game.table_name}.away_score) AS total_away").group("#{Game.table_name}.id").pluck[:id, :home_total, :away_total]
Couldn't test it, but it should work with single database query.

You need to use the group clause.
Score.where(period: ["q1", "q2"]).group(:game_id)
.select('game_id, sum(home_score) as home_score_sum, sum(away_score) as away_score_sum')
.all.map {|s| [s.game_id, s.home_score_sum, s.away_score_sum]}

Related

How to declare a jagged array in Dart

I have been googling for 2 days now and I have not found how to create a jagged list(array) in Dart.
There is this Dart - How to initialize a jagged array? but the given answer makes a normal list(array), what i want is something like this:
Not sure I understand the question. But is it something like this where we create a list of lists where each list in the list has a different length?
void main() {
final arr = [
[10, 9, 8],
[7, 5, 6, 88],
[30, 15],
[90],
[10, 20, 30, 40, 50]
];
print(arr); // [[10, 9, 8], [7, 5, 6, 88], [30, 15], [90], [10, 20, 30, 40, 50]]
}

Duplicate Hash Key unique Pair

I have a data pair:
[{:mobile=>21, :web=>43},{:mobile=>23, :web=>543},{:mobile=>23, :web=>430},{:mobile=>34, :web=>13},{:mobile=>26, :web=>893}]
How can I make this into:
[{mobile: [21, 23, 34, 26]}, {web: [43, 543, 430, 13, 893]}
When I look at the provide scenario I see the following solution:
data = [{:mobile=>21, :web=>43},{:mobile=>23, :web=>543},{:mobile=>23, :web=>430},{:mobile=>34, :web=>13},{:mobile=>26, :web=>893}]
keys = [:mobile, :web]
result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose).to_h
#=> {:mobile=>[21, 23, 23, 34, 26], :web=>[43, 543, 430, 13, 893]}
This first extracts the values of the keys from each hash, then transposes the the resulting array. This changes [[21, 43], [23, 543], [23, 430], ...] into [[21, 23, 23, ...], [43, 543, 430, ...]]. This result can be zipped back to the keys and converted into a hash.
To get rid of duplicates you could add .each(&:uniq!) after the transpose call, or map the collections to a set .map(&:to_set) (you need to require 'set') if you don't mind the values being sets instead of arrays.
result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose.each(&:uniq!)).to_h
#=> {:mobile=>[21, 23, 34, 26], :web=>[43, 543, 430, 13, 893]}
require 'set'
result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose.map(&:to_set)).to_h
#=> {:mobile=>#<Set: {21, 23, 34, 26}>, :web=>#<Set: {43, 543, 430, 13, 893}>}
References:
Array#map
Hash#values_at
Splat operator * (in hash.values_at(*keys))
Array#zip
Array#transpose
Array#to_h
Array#each
Array#uniq!
Enumerable#to_set

Finding elements repeating in many arrays in Rails

I have problem with comparing many arrays in one array. I need to get element which exists in every array. It's look like this one:
array= [[11,12,13,14],[55,66,13],[13,15,17,22,34],[4,6,8,13]]
I need to get only: 13 - because its on every array, how to get it ?
This should work
a.inject(:&)
You could use inject as mentioned by Nithin in another answer.
Another option is to use reduce:
ary = _
=> [
[11, 12, 13, 14],
[55, 66, 13],
[13, 15, 17, 22, 34],
[4, 6, 8, 13]
]
ary.reduce(:&)
=> [13]
# which is a short-hand for:
ary.reduce { |out, elem| out & elem }
=> [13]

Get unique ids from 2 has_many relationships in rails

I can't find a simple way to get the ids of pointfields from this relationship
pointtype has_and_belongs_to_many pointfields
pointfield has_and_belongs_to_many pointtypes
I do the following :
#pointtypes = current_project.points.map{|p| p.pointtype}.uniq
#pointtypes = #pointtypes - [nil] # tricky... Is this Railsy ?
#pointfield_ids = #pointtypes.map(&:pointfield_ids)
returns
[[16, 17, 18, 23, 24, 25, 26, 27, 28, 29], [16, 17, 32, 33, 34, 35, 36]]
and thus
#pointfield_ids.uniq!
is not working because there is two sub-arrays...
What I need is to get one single array with the unique ids of the pointfields (or the objects itself)

Rails Tutorial 3.2 Ch11 SQL syntax

I am learning rails from rails tutorial. I got a problem in the Section 11.3.1, the code in the Listing 11.44:
def self.from_users_followed_by(user)
followed_user_ids = user.followed_user_ids.join(', ')
where("user_id IN (?) OR user_id = ?", followed_user_ids, user)
end
will not return user_id in followed_user_ids.
After searching at stackoverflow, I found the solution here, which said that just remove the "join" method and it works for me.
But I am curious about why there is no error when I run RSPEC before remove the "join" method.
In Listing 11.41:
subject { Micropost.from_users_followed_by(user) }
it { should include(own_post) }
it { should include(followed_post) }
If the "join" method will make the SQL statement wrong, why RSPEC passed?
Does anyone have the same problem?
Update 2012.04.03
I used rails console to check the problem.
user = User.first
ids = ids = user.following_users.map(&:id).join(', ')
Which got
User Load (2.6ms) SELECT "users".* FROM "users" INNER JOIN "follows" ON
"follows"."followable_id" = "users"."id" AND "follows"."followable_type" = 'User' WHERE
"follows"."blocked" = 'f' AND "follows"."follower_id" = 1 AND "follows"."follower_type"
= 'User' AND "follows"."followable_type" = 'User'
=> "6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 55, 56, 5"
Then the SQL
Collection.where("user_id IN (?)", ids)
The result is
Collection Load (0.7ms) SELECT "collections".* FROM "collections" WHERE (user_id IN
('6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 55, 56, 5')) ORDER BY collections.created_at DESC
=> []
Which return an empty array.
But I got all my rspec passed. Still no idea.
Assuming the join creates a string '1,2,3', then perhaps you want to join("','") to have ('1','2','3'), but I don't think this will work - I'm sure PostgreSQL doesn't like IDs as strings.
Alternatively:
Squeel is a good SQL syntax gem where you could use:
user = User.first
ids = user.following_users.map(&:id)
Collection.where{(user_id.like_any ids)}
This will allow you to pass in the array of integers and Squeel will setup the query where:
SELECT "collections".* FROM "collections" WHERE (("collections"."user_id" LIKE 1 OR "collections"."user_id" LIKE 2 OR "collections"."user_id" LIKE 3))
EDIT: You can also use the syntax:
ids = User.first.following_users.pluck(:id)
Collection.find_by_user_id(ids)

Resources