Rails count values returned from pluck - sql

I am building a rails application, and I need to create some charts.
I am running this query to retrieve the answers from the user:
quiz = Quiz.select("answer1").where(completed: true).pluck(:answer1)
And the query returns for me this: [1, 2, 1, 1, 1]
I want to count the values and group them like this: { 1 => 4, 2 => 1 }
I have tried to use group by and count but it is not working, I could do this manually but I wanted to use just SQL to achieve this.
I remember to use group by and count using sql, but I am not sure how to do this using rails.

You can group('answer1') as described here
Quiz.where(completed: true).group('answer1').count
Hope it helped!

Try this one
Quiz.where(completed: true).group(:answer1).count(:answer1)

Related

Merge the results of two active record queries

I want to merge the results from the following queries:
Dispenser.includes(:reviews).where.not(reviews: { id: nil })
and
Dispenser.includes(:dispenser_reviews).where.not(dispenser_reviews: { id: nil })
I have tried simply placing a || in the middle of these two queries, but that does not give the expected result. I want to find all Dispensers with a review or a dispenser_review..
So let's say I have the following dispenser ids from each query:
[1, 2, 3] and [2, 3, 4] ..
The output should be the dispensers represented by the ids [1, 2, 3, 4]
You can accomplish that using https://github.com/activerecord-hackery/squeel rather than active record. It provides the more advanced functionality that Arel does not have out of the box.
That being said, your logic is gonna be pretty nasty. If you wanted to get the result set and you didn't mind two queries instead of one, I'd just join the two results with the + operator.
r1 = Dispenser.includes(:reviews)# ...
r2 = Dispenser.includes(:dispenser_reviews)# ...
result = r1 + r2
As for a squeel example, it'd be something like:
Dispenser.includes{reviews}.
includes{dispenser_reviews}.
where{(reviews.id.not_eq nil) | {dispenser_reviews.id.not_eq nil)}.
references(:all)
Joins will do an INNER JOIN and only return dispenser objects that have reviews or dispenser_reviews. Pipe '|' will get rid of dups.
Dispenser.joins(:reviews) | Dispenser.joins(:dispenser_reviews)
or to get ids
Dispenser.joins(:reviews).pluck(:id) | Dispenser.joins(:dispenser_reviews).pluck(:id)
You can also use arel and combine the two queries into one like this:
Dispenser.includes(:reviews, :dispenser_reviews).where((Review.arel_table[:id].not_eq(nil)).or DispenserReview.arel_table[:id].not_eq(nil)).references(:reviews, :dispenser_reviews)

How to order by largest amount of identical entries with Rails?

I have a survey where users can post answers and since the answers are being saved in the db as a foreign key for each question, I'd like to know which answer got the highest rating.
So if the DB looks somewhat like this:
answer_id
1
1
2
how can I find that the answer with an id of 1 was selected more times than the one with an id of 2 ?
EDIT
So far I've done this:
#question = AnswerContainer.where(user_id: params[:user_id]) which lists the things a given user has voted for, but, obviously, that's not what I need.
you could try:
YourModel.group(:answer_id).count
for your example return something like: {1 => 2, 2 => 1}
You can do group by and then sort
Select answer_id, count(*) as maxsel
From poll
Group by answer_id
Order by maxsel desc
As stated in rails documentation (http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html) when you use group with count, active record "returns a Hash whose keys represent the aggregated column, and the values are the respective amounts"
Person.group(:city).count
# => { 'Rome' => 5, 'Paris' => 3 }

Active Record query to match every subset element

In my RoR application, I've got a database lookup similar to this one:
Client.joins(:products).where({'product.id' => [1,2,3]})
Unfortunately this will return all clients that have bought product 1, 2 or 3 but I only want to get back the clients, that bought all of the three products. In other words, I'd like to write a query that matches for n elements in a given set.
Are there any elegant solutions for this?
This is not really elegant. But it should translate into the needed SQL.
Client.joins(:products).
where({'products.id' => [1,2,3]}).
group('users.id').
having('COUNT(DISTINCT products.id) >= 3')
Same answer with more dynamic way
ids = [1,2,3]
Client.joins(:products).
where({'products.id' => ids}).
group('users.id').
having('COUNT(DISTINCT products.id) >= ?', ids.size)

Query that finds objects with ALL association ids (Rails 4)

BACKGROUND: Posts have many Communities through CommunityPosts. I understand the following query returns posts associated with ANY ONE of these community_ids.
Post.joins(:communities).where(communities: { id: [1,2,3] })
OBJECTIVE: I'd like to query for posts associated with ALL THREE community_ids in the array. Posts having communities 1, 2, and 3 as associations
EDIT: Please assume that length of the array is unknown. Used this array for explanation purposes.
Try this,
ids=[...]
Post.joins(:communities).select(“count(communities.id) AS cnt”).where(id: ids).group(‘post.id’).having(cnt: ids.size)
ids = [1, 2, 3] # and etc
Post.joins(:communities).where("communities.id IN ?", ids)
Wish it helps .

ActiveRecord - Update single column data of different records in single query

Is it possible to update following data in one single query?
ID Seq
2 2
1 4
4 1
3 3
It would be best if it could be done with rails active records, else with sql query would be perfectly fine too.
Reason for doing so is I have scenario where I need to update a group of ids frequently based on ajax request. I believe having it done in single query is much more optimized.
I guess you're asking whether you can complete set of updates in a single transaction.
In rails, you can use ActiveRecord::Base.transaction for this purpose. For example, for a Model, you can:
Model.transaction do
Model.update(2, {:seq => 2} )
Model.update(1, {:seq => 4} )
Model.update(4, {:seq => 1} )
Model.update(3, {:seq => 3} )
end
We can not directly call multiple updates in a single query using Active Record. As you said we can run it as a sql query in rails.
sql = ActiveRecord::Base.connection();
sql.execute("INSERT into products (id,name,description) VALUES (id-1,'name4','desc4'),(id-2,'name5','desc5'),(id-3,'name6','desc7') ON DUPLICATE KEY UPDATE name=VALUES(name),description=VALUES(description);")
Found the solution I want from here and here.
This is how I do it with active records.
_params = ["12", "9", "13", "14", "15", "16"]
db = ActiveRecord::Base.connection();
query = "UPDATE #{self.table_name} SET display_order = CASE id "
_params.each_with_index do |d,i|
query += sanitize_sql(["WHEN ? THEN ? ",d,i])
end
query += "END "
query += "WHERE id in ('#{_params.join("','")}') "