count users within a given age range - ruby on rails - sql

I want to have a function to group users according to a certain age range. Then get their count which I can use to plot a bar-chart.
e
this statement is able to plot a chart of their ages, but it is each users age. which is what i want to eliminate. if you would like to know am using chartkick to make the charts.
<%= bar_chart User.group("date_trunc('year', age(dob))").count, {library: {title: "User's Age"}} %>
I want the ages returned as:
<%= bar_chart [["Below 10", users_with_ages_lying_in this_range.count],
["10-19", users_with_ages_lying_in this_range.count],
["20-29", ],
["30-39", ],
["40-49", ],
["above 50",]], {library: {title: "User's Age"}}
%>
in short I would like this line of code User.group("date_trunc('year', age(dob))").count to return only users for a given age range.
If you have any better ideas I would appreciate to know.
I'm using postgres DB

I had a similar need to find events within a range.
I made a class method on a model:
def self.in_range(start_range, end_range)
where "((start_date <= ?) and (end_date >= ?))", end_range, start_range
end
which is used like so:
events.in_range(start_range, end_range).order('start_date ASC')
I am sure a similar one could be created using age instead of start_date and end_date.

Related

How to connect ransacker query to ransack sort search parameter

Problem:
I am using the ransack gem to sort columns in a table. I have 2 models: Campaign and Course. A campaign has many courses, and a course belongs to one campaign. Each course has a number of total_attendees. My Campaigns table has a column for Total Attendees, and I want it to be sortable. So it would sum up the total_attendees field for each course that belongs to a single campaign, and sort based on that sum.
Ex. A campaign has 3 courses, each with 10 attendees. The Total Attendees column on the campaign table would show 30 and it would be sortable against total attendees for all the other campaigns.
I found ransackers:
https://github.com/activerecord-hackery/ransack/wiki/Using-Ransackers
and this SO question: Ransack sort by sum of relation
and from that put together a lot of what is below.
From Model - campaign.rb:
class Campaign < ApplicationRecord
has_many :courses
ransacker :sum_of_total_attendees do
query = "SELECT SUM(r.total_attendees)
FROM campaigns c
LEFT OUTER JOIN courses r
ON r.campaign_id = c.id
GROUP BY c.id"
Arel.sql(query)
end
end
From Model - course.rb:
class Course < ApplicationRecord
belongs_to :campaign, optional: true
end
View:
<th scope="col"><%= sort_link(#q, :sum_of_total_attendees, 'Total Attendees') %></th>
Controller - campaigns_controller.rb:
all_campaigns = Campaign.all
#q = all_campaigns.ransack(params[:q])
#campaigns = #q.result
Errors:
The ransacker query gives me the data I want, but I don't know what to do to get the right information .
Originally, when I clicked on the th link to sort the data, I got this error:
PG::CardinalityViolation: ERROR: more than one row returned by a
subquery used as an expression
I don't know what changed, but now I'm getting this error:
PG::SyntaxError: ERROR: syntax error at or near "SELECT"
LINE 1: SELECT "campaigns".* FROM "campaigns" ORDER BY SELECT SUM(r....
^
: SELECT "campaigns".* FROM "campaigns" ORDER BY SELECT
SUM(r.total_attendees)
FROM campaigns c
LEFT OUTER JOIN courses r
ON r.campaign_id = c.id
GROUP BY c.id ASC
This error seems to say that the ransack search parameter, #q and the ransacker query don't work together. There are two selects in this request, when there should definitely be only one, but the first one is coming from ransack, so I'm not sure how to address it.
How do I get my query to sort correctly with ransack?
Articles I've looked at but did not seem to apply to what I was looking to accomplish with this story:
Ransack Sort By Sum of Relation: This is the one I worked from a lot, but I'm not sure why it works for this user and not for me. They don't show what is changed, if anything, in the controller
Ransack Github Issue For Multiple Params: This doesn't cover the issue of summing table columns.
Rails Ransack Sorting Searching Based On A Definition In The Model: This didn't apply to my need to sort based on summed data.
Three Ways to Bend The Ransack Gem: This looks like what I was doing, but I'm not sure why theirs is working but mine isn't.

Group feedback by category and limit between date range

Feedback belongs to Category and has scope :between, ->(start_date, end_date) { where(created_at: start_date.beginning_of_day..end_date.end_of_day) }
Question is, how do we get the count of feedbacks grouped by category and scoped to a certain date range to get something like:
1.5.2013 - 31.5.2013
Good 3
Bad 10
etc.
I got so far: Category.group(:name).joins(:feedbacks).count, but I'm stuck on how to plug the between date condition there.
Feedback.between(sd,ed).joins(:category).group("categories.name").count
# => {"Good" => 3, "Bad" => 1}

How do I .group and .sum in a rails model using Postgres?

I have a functioning method in my development environment (SQLite) that looks this:
def self.ytd
Production.find(
:all,
conditions: ["year == ?", Time.now.year],
select: "carrier_id, amount, SUM(amount) as sum_amount",
group: :carrier_id
)
end
This method successfully searches through a table consisting of :carrier_id and :amount columns. It then sums the :amount column based on the grouped :carrier_id
I am trying to convert to a production environment using Postgresql. The below code successfully groups the records however I cannot sum the :amount. I have tried amending .sum("productions.amount") to the method without success. I am sure there is a simple solution, but it alludes me.. can someone please help? Thanks
def self.ytd
Production.select("DISTINCT ON (productions.carrier_id) productions.carrier_id, productions.amount ")
.where("productions.year = (?)", "#{Time.now.year}")
.group("productions.amount, productions.carrier_id, productions.id")
end
Removed DISTINCT ON, added SUM(amount) as sum_amount and grouped on :carrier_id yielded the desired results.
def self.ytd
Production.select("productions.carrier_id, SUM(amount) as sum_amount")
.where("productions.year = (?)", "#{Time.now.year}")
.group("productions.carrier_id")
end

Complex SQL Query in Rails - User.where(hash)

My starting point is basically Ryan Bates Railscast.
I have User model that I need to do some queries on. The model has a couple hourly rate attributes as follows:
#User migration
...
t.decimal :hour_price_high
t.decimal :hour_price_low
...
I have the query working in the User.where(Array) format where Array is formatted
["users.hour_price_high <= ? OR users.hour_price_low >= ? OR users.hour_price_low <= ? AND users.hour_price_high >= ?", hour_price_high, hour_price_low, hour_price_low, hour_price_high]
#This is simply a search of two ranges. Search for $40/h - $60/h.
#It will return an User who charge any overlapping price range. Such as one who charges $45/h - $65/h, etc.
I simply wish to convert this into Ruby syntax in the where statement.
My problem is how to represent the OR.
#This isn't the full query shown above..
User.where(:high_price_high => hour_price_low..hour_price_high, :hour_price_low => hour_price_low..hour_price_high)
Produces this SQL:
=> "SELECT `users`.* FROM `users` WHERE (`users`.`hour_price_high` BETWEEN 45 AND 60) AND (`users`.`hour_price_low` BETWEEN 45 AND 60)"
Which, of course, is wrong because of the AND. I need it to be:
=> "SELECT `users`.* FROM `users` WHERE (`users`.`hour_price_high` BETWEEN 45 AND 60) OR (`users`.`hour_price_low` BETWEEN 45 AND 60)"
How can I make this be an OR statement without busting out the old truth table from my sophomore E.E. classes?
Thanks!
When you chain several where methods or have a few arguments in one where method, then you always get AND between them, so when you want to have OR you need to use this syntax:
User.where("users.hour_price_high <= ? OR users.hour_price_low >= ? OR users.hour_price_low <= ? AND users.hour_price_high >= ?", hour_price_high, hour_price_low, hour_price_low, hour_price_high)
Note: please watch http://railscasts.com/episodes/202-active-record-queries-in-rails-3 in order to get more information about active record queries.

How to define new instantaneous variable row by row - RAILS3 BEGINNER

I was hoping somebody may be able to point me in the right direction...
I have a database called Info and use a find command to select the rows in this database which match a certain criteria
#matching = Info.find( :all, :conditions => ["product_name = ?", distinctproduct], :order => 'Price ASC')
I then pull out the cheapest of these items
#cheapest = #matching.first
Finally, I would like to create an instantaneous array which contains a list of #cheapest for a number of different search criteria. i.e. row 1 in #allcheapest is #cheapest for criteria 1, row 2 in #allcheapest is #cheapest for criteria 2, ...
Any help would be great, thanks in advance
Info.where(:product_name => distinct_product.to_s).order('Price ASC').first
to select the cheapest price for the product_name. Without more insight into how your database is structured, it is difficult to suggest how to obtain the latter, but you may try
Info.where(:product_name => distinct_product.to_s).order('Price ASC').group(:product_name)