轨。添加“count”列,其中包含来自关联表的值的总和

时间:2017-02-21 22:46:51

标签: ruby-on-rails ruby database

我有类别表和问题表。

类别模型中:

has_many :issues

问题模型中:

belongs_to :category

我能够编写一个查询,将query_count作为集合的虚拟属性返回:

Category.left_outer_joins(:issues).select('categories.*, COUNT(issues.*) AS issues_count').group('categories.id')

但是,我希望表上的实际列将issues_count存储为categories表中的值,如下所示:

id | name | created_at | updated_at | description | tags | issues_count

5 个答案:

答案 0 :(得分:6)

您可以在问题模型中添加issues_count列:

# app/models/issue.rb
class Issue < ApplicationRecord
  belongs_to :category, counter_cache: true
end

这将导致ActiveRecord自动更新category.issues_count字段。

您还必须创建迁移以添加此字段并更新现有记录:

class AddIssuesCountToCategory < ActiveRecord::Migration[5.0]
  def up
    add_column :categories, :issues_count, :integer, default: 0
    Category.reset_column_information
    Category.all.each do |c|
      Category.update_counters c.id, issues_count: c.issues.length
    end
  end
  def down
    remove_column :categories, :issues_count
  end
end

Ryan Bates有一个很好的RailsCasts:http://railscasts.com/episodes/23-counter-cache-column

另请参阅Rails指南:http://edgeguides.rubyonrails.org/association_basics.html#options-for-belongs-to-counter-cache

答案 1 :(得分:1)

SELECT categories.*, COUNT(issues.id) as issue_count
FROM categories
INNER JOIN issues
ON issues.category_id = categories.id 
GROUP BY categories.id

上述查询将满足您的需求。所以在ruby代码中,它将如下所示

Category.joins(:issues).select("categories.*, COUNT(issues.id) AS issues_count").group('categories.id')

答案 2 :(得分:0)

您可以使用left_outer_join执行此操作,如下所示:

Category.left_outer_joins(:issues).distinct.select("categories.*, COUNT(issues.*) AS issues_count").group('categories.id')

这将生成类似以下内容的SQL:

SELECT DISTINCT categories.*, COUNT(issues.*) AS issues_count FROM "categories" 
    LEFT OUTER JOIN "issues" 
    ON "issues"."category_id" = "categories"."id" 
    GROUP BY categories.id

答案 3 :(得分:-1)

你需要它作为查询吗?否则你可以在你的控制器中写这样:

@categories = Category.all

要解决每个类别的所有问题,您可以这样做

@categories.each{|c| puts c.issues.count}

或在您的观点中以通常的方式使用它:

@categories.each do |c|

c. ...您可以在c.之后调用所有类别列  c.issues.count为您提供了category_idc.id

的问题

否则试试这个:

Category.joins( '问题')。为了( 'issues.count')

答案 4 :(得分:-1)

在控制器文件上 -

@categories = Category.all

它将从类别模型中返回所有类别。

在你的观点上 -

<table>
 <tr>
  <th>Category Name</th>
  <th>Issue Count</th>
 </tr>
 <% @categories.each do |category| %>
  <tr>
   <td><%= category.name %></td>
   <td><%= category.issues.count %></td>
  </tr>
 <% end %>
</table>

这里我们按每个循环迭代每个类别,在第二列中我们只打印否。一类问题。