29

親テーブルのすべての行を効率的に取得し、各行にある子の数をカウントする「レールの方法」とは何ですか?

counter_cacheいくつかの時間条件に基づいてこれらのカウントを実行したいので、使用したくありません。

決まり文句のブログの例: 記事の表。各記事には 0 個以上のコメントがあります。

過去 1 時間、1 日、1 週間に各記事に寄せられたコメントの数を取得できるようにしたいと考えています。

ただし、理想的には、リストを反復処理して記事ごとに個別の SQL 呼び出しを行いたくないし:include、すべてのデータをプリフェッチしてアプリ サーバーで処理するために使用したくありません。

1 つの SQL ステートメントを実行して、すべての情報を含む 1 つの結果セットを取得したいと考えています。

私は完全な SQL をハードコーディングできることを知っています。おそらく a を使用して、 、、およびパラメータ.findを設定することもできます...しかし、「より良い」方法があるかどうか疑問に思っています...別名「Rails Way」:joins:group:conditions

4

5 に答える 5

29

このactiverecord呼び出しは、必要なことを実行する必要があります。

Article.find(:all, :select => 'articles.*, count(posts.id) as post_count',
             :joins => 'left outer join posts on posts.article_id = articles.id',
             :group => 'articles.id'
            )

これにより、記事オブジェクトのリストが返されます。各オブジェクトにはpost_count、記事の投稿数を文字列として含むメソッドが含まれています。

このメソッドは、次のようなsqlを実行します。

SELECT articles.*, count(posts.id) AS post_count
FROM `articles`
LEFT OUTER JOIN posts ON posts.article_id = articles.id
GROUP BY articles.id

興味があれば、これはそのようなクエリを実行したときに表示される可能性のあるMySQLの結果のサンプルです。

+----+----------------+------------+
| id | text           | post_count |
+----+----------------+------------+
|  1 | TEXT TEXT TEXT |          1 |
|  2 | TEXT TEXT TEXT |          3 |
|  3 | TEXT TEXT TEXT |          0 |
+----+----------------+------------+
于 2009-04-28T06:04:05.287 に答える
4

SQL の観点からは、これは簡単に見えます。新しいクエリを作成するだけです。

Railsの観点から、あなたが言及する値は計算された値です。したがって、 を使用するfind_by_sqlと、 Model クラスは計算フィールドを認識しないため、クエリを Rails の言語に変換できたとしても、計算された値を文字列として返します。以下のリンクされた質問を参照してください。
(その質問に対する回答から)一般的な傾向は、別のクラスにロールアップ/目的の値の計算を担当させることでした。

文字列ではなく正しいデータ型でSUM(columnName)属性を返すようにレールを取得する方法は?

于 2009-04-28T05:39:18.247 に答える
4

この問題を解決するために私が使用した簡単な方法は

私のモデルでは、次のことを行いました。

class Article < ActiveRecord::Base
  has_many :posts

  def count_posts
    Post.where(:article_id => self.id).count
  end
end

たとえば、次のように使用できます。

Articles.first.count_posts

それがより効率的な方法であるかどうかはわかりませんが、それは解決策であり、私の意見では他の方法よりもエレガントです。

于 2014-11-22T20:14:53.517 に答える