サブテーブルのカラムの合計でソートしたい
- 評価
- クリップ 0
- VIEW 551

退会済みユーザー
user モデルが has_many: points をもっていて
point モデルが belongs_to の user_id と point 値と create_at をもっています
指定したユーザー(リレーションでもってる)に対して
ユーザごとに points レコードの一定期間内の point (user.points.point) を集計してランキングにしたいです
期間は term_since, term_until で変数でもっています
最終的にほしいのは select {user_id, rank, point} で
まだランキングをつける処理はかけていないんですが
とりあえず user_id とユーザに関連しているポイントレコードの一定期間内の集計のソートを
select {user_id, point} で取り出そうとしたのですが
ActiveRecord のクエリーをかくのにまだなれていなくて Syntaxerror がなかなかとれません
users.select(id, sum(:points).where(create_at >= term_since && create_at <= term_until) as point)
.order(:point)
.find_each do |id, point|
users.select(id, points.where(create_at >= term_since && create_at <= term_until) as point))
.select(sum(point) as point)
.order(:point)
.find_each do |id, point|
where や sum をどこにつければいいのかわからなくて
どのようにかけばよいのでしょうか
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
ActiveRecord の集計は、集計する対象を主語にする方が自然だと思います。
検証してないですが、以下のようなイメージでどうでしょうか??
Point.joins(:user).where(created_at: 期間の始まり..期間の終わり).group(:user_id).sum(:point)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
何にでも as point って付けるものではないはず。
憶測で、
users.select(id, points.where(create_at >= term_since && create_at <= term_until))
.select(sum(point) as sum_point)
.order(sum_point)
or
users.select(id, points.where(create_at >= term_since && create_at <= term_until))
.select(sum(point) as sum_point)
.order(sum(point))
では?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
集計結果をviewにまとめておけばもっと楽できそうな気がします
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
数日どうしても syntax error がとれなかったんですが
SQL の途中にコメント行をはさんでたせいで syntax error になってるようでした…
ruby はメソッドチェーンの途中でコメントや空行は使えないのですね…
いろいろ回答をいただいたのにどれも正しかったみたいで申し訳ないです
users.includes(:points)
.where(created_at: term_since..term_until)
.group(:user_id)
.select("user_id, sum(point)")
.order('sum_point')
Point.where(user: users, created_at: term_since..term_until)
.group(:user_id)
.order('sum_point desc')
.sum(:point)
どちらも動きました
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.19%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/11/30 13:50
指定した users (リレーション)に対してのみのポイントがとりたいんですが
users = users.plunk(:id)
Point.joins(:user).where(user_id in users).where(created_at: 期間の始まり..期間の終わり).group(:user_id).sum(:point)
みたいに1度IDリストを取得して2回SQLを発行しかないですか?
2018/11/30 14:52
これで、どうでしょうか? `#pluck`はwhereに入れるとそのままクエリにもなります。
あと、この場合joinsは要らないですね。
```Ruby
Point.where(user_id: users.pluck(:id), created_at: 期間の始まり..期間の終わり).group(:user_id).sum(:point)
```
2018/11/30 15:28
これをよむと sum は読んだ時点でハッシュになってリレーションじゃなくなっちゃうみたいなんですが
その後 order をかきたければ select(sum) を使ったほうがいいんでしょうか
今回の場合 sum の結果で sort してさらに for_each でランクをつけたいので…
2018/11/30 17:46
あと、SQL二回発行していたので修正してます。
```Ruby
Point.where(user: users, created_at: 期間の始まり..期間の終わり).group(:user_id).order('sum_point desc').sum(:point)
```
参考: http://blog.scimpr.com/2015/04/25/activerecord4%E3%81%A7%E3%81%AE%E9%9B%86%E8%A8%88%E3%82%92%E3%81%84%E3%82%8D%E3%81%84%E3%82%8D%E3%81%BE%E3%81%A8%E3%82%81%E3%81%9F/
2018/12/03 15:36
後にかいていただいた方だと .group のところで syntax error になります…
リレーションで users が与えられるといったのですが正確にはもう1つ上の usergroup というテーブルがあってその中のアソシエーションで users を参照してるんですが
Point.where(user: @group.users, created_at: term_since..term_until).group(:user_id).order('sum_point desc').sum(:point)
とはかけないのでしょうか…
@group.users 自体は表示させてみるとエラーにはなりませんでした
2018/12/03 16:52