我想在rails中执行mysql函数GROUP_CONCAT。 我正在使用活动记录的计算方法。 像这样的self.calculate(:group_concat,:id)
我不知道这是否正确。
关于如何在rails中执行group_concat的任何想法? 以及activerecord的find方法。
答案 0 :(得分:0)
正如@Camway上面所说,使用适当的Rails方法轻松完成JOINing,SELECTing和GROUPing。例如,假设我有用户和区域,用户可以有0到多个区域,区域可以有0到多个用户。
这是我的区域模型:
class Region < ActiveRecord::Base
# attributes: id (integer), code (string)
has_and_belongs_to_many :users
end
这是我的用户模型:
class User < ActiveRecord::Base
# attributes: id (integer), email (string)
has_and_belongs_to_many :regions
end
当然,还有 regions_users 连接表与region_id和user_id整数字段。
为了获得通用的GROUP_CONCAT工作,它可以提取每个用户所附加的所有区域的代码,我只需要向User模型添加这样的类方法:
class User < ActiveRecord::Base
# attributes: id (integer), email (string)
has_and_belongs_to_many :regions
class << self
def regions_listing
joins(:regions)
.select("DISTINCT users.email, GROUP_CONCAT(DISTINCT regions.region_code ORDER BY regions.region_code) AS regions_list")
.group("users.email")
.order("users.email")
end
end
end
因此,只需使用相应的代码,以下内容将拉动所有用户,按电子邮件地址排序。
ruby > User.regions_listing
=> [#<User email: "joe@blow.com">,#<User email: "sally@mae.com">,#<User email: "billy@bob.com">,#<User email: "jane@doe.com">,#<User email: "big@ed.com">]
这些返回的对象中的每一个都有一个 #regions_list 属性读取器,它将为您提供通过regions_users表附加到该用户的区域的代码串联列表。
通过简单调用#map:
可以看到这一点ruby > User.regions_listing.map { |u| [u.email, u.regions_list] }
=> [["joe@blow.com", "0,1,2,3,4,5"], ["sally@mae.com", "1,2,5"], ["billy@bob.com", "0,4"], ["jane@doe.com", "3"], ["big@ed.com", "2,3,4,5"]]
请注意,由于这是使用适当的AREL支持的AR方法,因此可链接。也就是说,您可以将“。regions_listing”添加到几乎任何针对User模型的AR查询的末尾,它将为您提供查询选择的任何用户对象的组连接方法/数据起来。
因此:
ruby > User.where("users.email like 'b%'").regions_listing.map { |u| [u.email, u.regions_list] }
=> [["billy@bob.com", "0,4"], ["big@ed.com", "2,3,4,5"]]
您还可以使用HAVING获取制作的#regions_list字段中的数据,例如查找连接到区域0和区域4的所有用户:
ruby > User.regions_listing.having("regions_list LIKE '%0%4%'").map { |u| [u.email, u.regions_list] }
=> [["joe@blow.com", "0,1,2,3,4,5"], ["billy@bob.com", "0,4"]]