【问题标题】:Select oldest HABTM record with group by clause使用 group by 子句选择最旧的 HABTM 记录
【发布时间】:2019-09-04 16:13:35
【问题描述】:

我想在管理页面(带有chartkick)上显示一个折线图,其中包含与其最早导出日期相关的分数增量。

我有以下型号:

# score.rb

class Score < ApplicationRecord
  has_and_belongs_to_many :export_orders, join_table: :scores_export_orders
end

# export_order.rb

class ExportOrder < ApplicationRecord
  has_and_belongs_to_many :scores, join_table: :scores_export_orders
end

对于每个至少有一个ExportOrderScore,我如何选择对应的ExportOrder 和最早的created_at(仅日期格式)?

我看过this,但我的情况是HABTM关系而不是简单的has_many。

我尝试了这段代码,以至少获得最旧的导出日期和分数数量之间的映射:

sql = "
SELECT
  COUNT(DISTINCT scores.id), MIN(export_orders.created_at::date)
FROM
  scores
INNER JOIN
  scores_export_orders
ON
  scores.id = scores_export_orders.score_id
INNER JOIN
  export_orders
ON
  export_orders.id = scores_export_orders.export_order_id
GROUP BY
  export_orders.created_at::date
".split("\n").join(' ')
query = ActiveRecord::Base.connection.execute(sql)
query.map { |v| [v['count'], v['min']] }

但总分数大于所有具有导出日期的分数。 有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

    试试:

    class Score < ApplicationRecord
      has_and_belongs_to_many :export_orders, join_table: :scores_export_orders
    
      def earliest_export_date
        export_orders.pluck(&:created_at).min
      end
    end
    

    这会让你调用@score.earliest_export_date,它应该会返回你想要的值。

    我也认为这是在 ruby​​ 中执行此操作的最高效方式,尽管有人可能会纠正我。

    【讨论】:

    • 要收集所有日期,我可以在所有分数上运行map,然后使用您的方法。这可能导致约 10 秒的延迟,约 1500 个分数条目。有没有更好的方法?
    【解决方案2】:

    下面的性能比Mark's solution 更好,因为它依赖于纯SQL。基本上,GROUP BY 子句要求按scores_export_orders.score_id 而不是export_orders.created_at 分组:

    sql = "
    SELECT
      COUNT(DISTINCT scores_export_orders.score_id), MIN(export_orders.created_at::date)
    INNER JOIN
      scores_export_orders
    INNER JOIN
      export_orders
    ON
      export_orders.id = scores_export_orders.export_order_id
    GROUP BY
      scores_export_orders.score_id
    ".split("\n").join(' ')
    query = ActiveRecord::Base.connection.execute(sql)
    query.map { |v| [v['count'], v['min']] }
    

    我在 ActiveRecord 指令中找不到完全等效的指令(所有这些尝试都给了我奇怪的结果),所以执行 SQL 也可以解决问题。

    【讨论】:

      猜你喜欢
      • 2022-08-11
      • 2018-09-18
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-11
      • 1970-01-01
      相关资源
      最近更新 更多