質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

4回答

1041閲覧

サブテーブルのカラムの合計でソートしたい

退会済みユーザー

退会済みユーザー

総合スコア0

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2018/11/29 06:10

編集2018/11/30 05:02

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 をどこにつければいいのかわからなくて
どのようにかけばよいのでしょうか

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

ActiveRecord の集計は、集計する対象を主語にする方が自然だと思います。
検証してないですが、以下のようなイメージでどうでしょうか??

Ruby

1Point.joins(:user).where(created_at: 期間の始まり..期間の終わり).group(:user_id).sum(:point)

投稿2018/11/29 06:38

samemuramura

総合スコア23

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/11/30 04:50

これだと Point レコード全体が対象になってしまうので 指定した 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を発行しかないですか?
samemuramura

2018/11/30 05:52

usersのリレーションがあったんですね、見落としてましたm(_ _)m これで、どうでしょうか? `#pluck`はwhereに入れるとそのままクエリにもなります。 あと、この場合joinsは要らないですね。 ```Ruby Point.where(user_id: users.pluck(:id), created_at: 期間の始まり..期間の終わり).group(:user_id).sum(:point) ```
退会済みユーザー

退会済みユーザー

2018/11/30 06:28

https://qiita.com/shin_semiya/items/072c8835b77eb753b993 これをよむと sum は読んだ時点でハッシュになってリレーションじゃなくなっちゃうみたいなんですが その後 order をかきたければ select(sum) を使ったほうがいいんでしょうか 今回の場合 sum の結果で sort してさらに for_each でランクをつけたいので…
退会済みユーザー

退会済みユーザー

2018/12/03 06:36

pluck を使う方法だと動いたのですがおっしゃるようにSQLが2度発行されます 後にかいていただいた方だと .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 07:52

主語をポイントにするとレコードが存在しない0ポイントのユーザがでてこないみたいで、やっぱりユーザを主語にして includes する必要があるみたいです
guest

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)

どちらも動きました

投稿2018/12/03 07:00

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

集計結果をviewにまとめておけばもっと楽できそうな気がします

投稿2018/11/30 02:47

yambejp

総合スコア114769

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/11/30 02:52

これは非同期処理の中で定期的に走らせるバッチ処理で view はありません users 数と同じ数の (user_id, rank, point) というランキングレコードをあらかじめ作成しておいて 各ユーザは自分のランクだけ参照する感じです
guest

0

何にでも as point って付けるものではないはず。
憶測で、

SQL

1users.select(id, points.where(create_at >= term_since && create_at <= term_until)) 2 .select(sum(point) as sum_point) 3 .order(sum_point)

or

SQL

1users.select(id, points.where(create_at >= term_since && create_at <= term_until)) 2 .select(sum(point) as sum_point) 3 .order(sum(point))

では?

投稿2018/11/29 06:22

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/11/30 04:40

すみません 参考にしてかいてみてるんですがやはり .select(sum(point) as sum_point) が syntax error になります
Orlofsky

2018/11/30 05:25

お力になれずすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問