【问题标题】:ActiveRecord: complex query with Sum, Join, Group By and Select multiple fieldsActiveRecord:具有 Sum、Join、Group By 和 Select 多个字段的复杂查询
【发布时间】:2014-11-18 07:09:34
【问题描述】:

我已经为此查询了几天,但仍然没有找到解决方案。

有我的模型

class UserObject < ActiveRecord::Base
  self.table_name = "user_objects"
  belongs_to :user, class_name: 'User'
  belongs_to :the_object, class_name: 'Object'
end

class Object < ActiveRecord::Base
  self.table_name = 'objects'

  has_many :user_objects, class_name: 'UserObject', foreign_key: :the_object_id, inverse_of: :the_object
  has_many :users, through: :user_objects
end

class User < ActiveRecord::Base
  self.table_name = "users"
end

这是我的架构

  create_table "objects", force: true do |t|
    t.float    "importance",        default: 0.5, null: false
  end

  create_table "user_objects", force: true do |t|
    t.integer  "user_id"
    t.integer  "the_object_id"
    t.float    "score",              default: 0.0,   null: false
  end

  create_table "users", force: true do |t|
    t.string   "first_name"
    t.string   "last_name"
  end

我需要查询选择 objects.importanceuser_objects.score 的总和。但我也必须只选择属于user1user2objects 进行查询。

我为选择对象写了一个查询。重要性

Object.select("objects.importance").joins(:user_objects).
                                    where(user_objects: {user_id: [user1_id,user2_id]}).
                                    group(objects: :id).
                                    having('COUNT("user_objects"."id")=2')

它被转换成

SELECT objects.importance FROM "objects" INNER JOIN "user_objects" ON "user_objects"."the_object_id" = "objects"."id" WHERE "user_objects"."user_id" IN (2, 7) GROUP BY "objects"."id" HAVING COUNT("user_objects"."id")=2

当我执行这个查询时,我得到了这个响应

[#<Object id: nil, importance: 0.5>, #<Object id: nil, importance: 0.5>]

响应的对象数量正常。但是我仍然不知道如何计算user_objects.score的这个查询总和。下一个查询不起作用

Object.select("objects.importance, SUM(user_objects.score)").
       joins(:user_objects).
       where(user_objects: {user_id: [user1_id,user2_id]}).
       group(objects: :id).having('COUNT("user_objects"."id")=2')

我期待这样的回应

[#[<Object id: nil, importance: 0.5>, 0.2], #[<Object id: nil, importance: 0.5>,0.3]]

非常感谢您在解决这个问题时给我的任何帮助。

【问题讨论】:

  • 既然逻辑简单,为什么不用原生SQL呢?
  • 因为原始 SQL 的可读性较差,而且它不是 Rails 方式
  • SQL 是关系数据库领域的通用语言。许多框架方言是苍白的模仿,实现了功能的残缺不全的子集,甚至在可读性方面也差强人意。当然,如果您的母语是芬兰语,您会发现芬兰语比英语“更易读”。但无论哪种方式,一切都必须翻译成 SQL,因为这毕竟是 RDBMS 的语言。 SQL 本来可以设计得更巧妙,但对于英语的奇怪方面也是如此,它是世界通用语,我们在这里使用它。
  • Erwin,你说得对,SQL 是一种通用语言,但在 Rails 代码中使用 ActiveRecord 更可取。并且“英语”原始 SQL 的可读性较差,因为它被“芬兰语”Ruby 代码包围。

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


【解决方案1】:

Ок.我找到了解决方案。这是正确的查询。

Object.joins(:user_objects).
       where(user_objects: {user_id: [user1_id,user2_id]}).
       group(objects: :id).
       having('COUNT("user_objects"."id")=2').
       pluck("objects.importance, SUM(user_objects.score)")

问题出在select 方法中,因为它创建了调用此方法的类的对象。所以不可能在少数型号的select属性中选择一个。但是pluck 返回结果数组,其中包含字段的,因此我们可以从不同的表中选择字段。 就是这样。这么简单!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多