sql | Dmytro Shteflyuk's Home https://kpumuk.info In my blog I'll try to describe about interesting technologies, my discovery in IT and some useful things about programming. Tue, 08 Sep 2015 00:09:46 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Using sub-queries to avoid multiple DB requests in Rails https://kpumuk.info/ruby-on-rails/using-sub-queries-to-avoid-multiple-db-requests-in-rails/ https://kpumuk.info/ruby-on-rails/using-sub-queries-to-avoid-multiple-db-requests-in-rails/#comments Thu, 12 Apr 2007 06:12:22 +0000 http://kpumuk.info/ruby-on-rails/using-sub-queries-to-avoid-multiple-db-requests-in-rails/ When I worked on Best Tech Videos with Alexey Kovyrin, we faced a problem of filtering videos by category with selecting posts categories in the same query. It was easy to solve the problem, but there is one query optimization trick exists. For example, we are developing blogging software. We have Post and Category model, […]

The post Using sub-queries to avoid multiple DB requests in Rails first appeared on Dmytro Shteflyuk's Home.]]>
When I worked on Best Tech Videos with Alexey Kovyrin, we faced a problem of filtering videos by category with selecting posts categories in the same query. It was easy to solve the problem, but there is one query optimization trick exists.

For example, we are developing blogging software. We have Post and Category model, where post could have one or more categories (many-to-many relation):

1
2
3
4
5
6
7
class Post < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

We need to display posts on the page along with categories for each one. The simplest way is to do find with :include:

1
Post.find :all, :include => :categories

And corresponding helper:

1
2
3
def show_categories(post)
  post.categories.map(&:name).join(' ')
end

But what if you need to filter off posts by category? Here is example:

1
2
3
Post.find :all,
          :include => :categories,
          :conditions => ['categories.id = ?', category_id]

It works, but there is one small trouble: you would get not all categories! Now we could fix it in helper:

1
2
3
4
def show_categories(post)
  # reload categories
  post.categories(true).map(&:name).join(' ')
end

In this case categories for all posts would be requested in separate queries. It’s not so good, therefor I propose to use sub-query:

1
2
3
Post.find :all,
          :include => :categories,
          :conditions => ['EXISTS (SELECT tmp_cp.category_id FROM categories_posts tmp_cp WHERE posts.id = tmp_cp.post_id AND tmp_cp.category_id = ?)', category_id]

Now posts would be filtered by category and all categories of posts would be loaded properly. Do you have other ideas?

The post Using sub-queries to avoid multiple DB requests in Rails first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/ruby-on-rails/using-sub-queries-to-avoid-multiple-db-requests-in-rails/feed/ 8