Rails postgres query - Model.where(model.has_many_relationship_item.count >= 2)? - sql

I need to return an array of a category where a particular item of which it has_many, has a .count >= 2
I know this sytax is wrong, but I'm trying to figure out the correct way, any tips??
Model.where(model.has_many_relationship_item.count >= 2) ??
Thanks in advance!!

Category.joins(:items).group("cateogry.id").having("COUNT(items.id) >= 2")

The only way I know how to do this is:
Model.joins(:items).group('models.id').having('count(items.id) >= 2')
assuming (for example) the class of the related model is Item

Model.joins(:association).group('model_table.id').having('COUNT(association_table.id) >= 2')

Related

How to get the day that I have more orders created

I have a rails application and I want to know in my class Order the day that I have more creations.
Could you help me please :D
I'm using as database the postgresql
Thank you in advance.
max_orders_in_a_day = Order.all.group_by{ |x| x.created_at.all_day }.sort_by { |a,b| b.length }.last
max_orders_in_a_day[0] #=> The day
max_orders_in_a_day[1] #=> An array with the related Order objects

Rails simple sql comparison with another attribute

I think this should be quite simple. I want to do something like:
User.where("created_at < ?", :updated_at)
updated_at is another attribute of the User
Thanks in advance!
You can do the following:
john = User.where(username: 'john').first
users_updated_before_john = User.where('created_at < ?', john.updated_at)
After you commented:
I'm trying to do something like User.where("created_at < ?", Date.today - :updated_at) And I want the attribute created_at be compared with the updated_at for each user, not with the a static one.
Here is how you do it: (PostgreSQL 9.1 syntax!)
User.where('users.created_at::date < (users.updated_at::date - integer '5')')
The documentation about Date/Time functions in PostgreSQL (9.1):
http://www.postgresql.org/docs/9.1/static/functions-datetime.html

Get all records with child records OR field length > 250

I have a Comment model which has-many attachments. What I want to return, is all of the comments which either have one or more attachment records, OR whose comment is longer than 250 characters.
Is there any way I can do this without writing it entirely in pure SQL? I'm struggling to build up a WHERE clause in just the rails method. It's not quite as simple as I'd hoped :(
Ideally I want this to be a scope but whatever will work is fine
You could try:
Comment.includes(:attachments).where('attachments.comment_id IS NOT NULL OR LEN(comments.content) > 250')
The WHERE clause should follow the pattern o the following pseudo-code
WHERE Length(Comment_field) > 250
OR EXISTS (Select COMMENT_ID from attachments)
Jump into the irb or rails c (console) do this from command-line to get it then plug it in.
c = YourCommentModel.where('attachments > ?', 1)
len250 = c = YourCommentModel.where('attachments.length> ?', 250)
first one gives comments of greater than 1, second gives comments > 250

ActiveRecord condition with count less than for association

I have a User that has_many messages.
I need a create a query that will
'Get me all users who's (message.opened == false) count < 3'
Right now, I am using User.all, iterating through all users, and counting manually. I understand that this isn't very efficient and it can be all done in one query, but I am new to SQL/ActiveRecord so need some help here.
Thanks
Assuming Rails 3 syntax. You can do something like:
User.joins(:messages).where(:messages => {:opened => false}).group(:user_id).having("COUNT(messages.id) < 3)
This should work:
User.includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
This will create two queries, one for the grouped query, and one for eager loading the resulting users and messages with a join.
Here is solution to your problem
User.includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
but what else you can do is to create a scope for this
scope :not_opened_less_three_count, includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
And then you can use it anywhere you needed as follow
User.not_opened_less_three_count
Try this
User.includes(:messages).group('users.id').having('SUM(IFNULL(messages.opened = 0, 1)) < 3')
It works at least on MySQL, AND assuming your boolean true are 1 in database.
EDIT I had reversed the condition
PS IFNULL is there to handle if messages.opened can be NULL

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.