Im looking to query all Users without Comments in a single sql query?
Models:
class User < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
end
So I want the opposite of this:
User.joins.(:comments).group('users.id')
But not like this: (because it generates two queries)
User.where.not(id: Comment.pluck(:user_id))
Maybe something like this?
User.joins.not.(:comments).group('users.id')
Thanks for any input!
The main difference is that when using includes the eager loading is used. Eager loading allows you to optimize data retrieval by avoiding additional queries to the database.
What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.
The Relation Class. Having queries return an ActiveRecord::Relation object allows us to chain queries together and this Relation class is at the heart of the new query syntax. Let's take a look at this class by searching through the ActiveRecord source code for a file called relation.
Eager loading is a way to find objects of a certain class and a number of named associations. Here I share my thoughts on using it with Rails. What are N + 1 queries? It mainly occurs when you load the bunch of objects and then for each object you make one more query to find associated object.
You can accomplish this with:
User.includes(:comments).where.not(comments: { id: nil })
This will result in raw SQL that looks something like:
SELECT DISTINCT `users`.`*` FROM `users` LEFT OUTER JOIN `comments` ON `comments`.`user_id` = `users`.`id` WHERE `comments`.`id` IS NULL
For accomplishing this via a subquery, see the below answer.
Old Answer:
You can do something like
User.where.not(id: Comment.select(:user_id))
If you wanted a single (though nested) query.
Otherwise, check out http://guides.rubyonrails.org/active_record_querying.html#joining-tables for using an outer join.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With