【问题标题】:How do I group all of the objects on my model by a column on the same model without using a join model?如何在不使用连接模型的情况下按同一模型上的列对模型上的所有对象进行分组?
【发布时间】:2020-03-15 09:16:41
【问题描述】:

我有一个模型Position,它具有以下架构:

# Table name: positions
#
#  id                :bigint           not null, primary key
#  action            :integer
#  current_price     :float
#  current_value     :float
#  status            :integer          default("0")
#  ticker            :string
#  volume            :integer
#  created_at        :datetime         not null
#  updated_at        :datetime         not null
#  portfolio_id      :integer
#  stock_id          :integer

  belongs_to :portfolio
  belongs_to :stock

我的User 模型如下所示:

  has_one :portfolio, dependent: :destroy
  has_many :positions, through: :portfolio, dependent: :destroy

我的Portfolio 模型如下所示:

class Portfolio < ApplicationRecord
  belongs_to :user
  has_many :positions
end

我想要做的是返回所有由positionticker 分组的current_user 的位置,而不必在stock 模型上执行join,作为数组或一些 AR 对象,我可以对其进行迭代并列出每个组中的每个 AR 对象。

我成功的方法是这样的:

@positions = current_user.positions.buy.open.order(transaction_date: :desc)
@grouped_stocks = @positions.joins(:stock).group_by { |ps| ps.stock.ticker }

但是,理想情况下,我只想在第一个查询中执行此操作。

我尝试了以下方法,但它们都不起作用。

current_user.positions.buy.open.group("ticker")
=> #<Position::ActiveRecord_AssociationRelation:0x3ffdf189d6d4>

current_user.positions.buy.open.order(transaction_date: :desc).group("ticker.name")
      Position Load (2.9ms)  SELECT "positions".* FROM "positions" INNER JOIN "portfolios" ON "positions"."portfolio_id" = "portfolios"."id" WHERE "portfolios"."user_id" = $1 AND "positions"."action" = $2 AND "positions"."status" = $3 GROUP BY ticker.name ORDER BY "positions"."transaction_date" DESC  [["user_id", 2], ["action", 0], ["status", 0]]
  Position Load (2.3ms)  SELECT  "positions".* FROM "positions" INNER JOIN "portfolios" ON "positions"."portfolio_id" = "portfolios"."id" WHERE "portfolios"."user_id" = $1 AND "positions"."action" = $2 AND "positions"."status" = $3 GROUP BY ticker.name ORDER BY "positions"."transaction_date" DESC LIMIT $4  [["user_id", 2], ["action", 0], ["status", 0], ["LIMIT", 11]]
=> #<Position::ActiveRecord_AssociationRelation:0x3ffdefe0a7a4>

我该怎么做?

编辑

请参阅下面的示例屏幕截图,了解我希望如何组织结果:

【问题讨论】:

  • positions 表中是否有任何名为ticker 的列?如果不加入,你将如何分组?
  • 是的,在问题顶部的架构表中查找positions
  • ticker是一列位置,tickers.name从哪里来?
  • @SebastianPalma 好点。那是错误的。我更新了问题以将其删除。它仍然返回了一个类似的 AR Association Relation 对象,这对我没有多大帮助。
  • 您使用的是什么关系型数据库? current_user.positions.buy.open.select('distinct on (positions.ticker) *') 呢?

标签: ruby-on-rails activerecord ruby-on-rails-5


【解决方案1】:

我看到你在位置表上有ticker,而不是stocks 表。因此,如果是这种情况,您无需查看stocks 表。 (最好放在股票表上) transaction_date 也没有在上面列出,所以我假设它在 positions 表上。

这或多或少是您所拥有的,我假设 group('ticker.name') 不适合您,因为您需要按 positionsticker 列进行分组。

@positions_grouped_by_ticker = current_user.positions.buy.open.group('positions.ticker').order(transaction_date: :desc)

使用 group 将返回一个数组数组,而不是 AR 集合。

# view.html.erb
@grouped_positions.each do |stock_positions|
  <%= render stock_positions %>
end

【讨论】:

  • 当我尝试这个时,它不起作用。 ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "positions.id" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT "positions".* FROM "positions" INNER JOIN "portfolios...
  • 啊,我明白了!我已经更新了上面的查询。此人有类似问题stackoverflow.com/a/48369842/1861295
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多