ActiveRecord将具有相同列值的行合并为一个

时间:2018-07-13 20:19:09

标签: sql ruby activerecord

在我的Rails应用程序中,我试图合并来自多行的数据。

我的表格如下所示。

Name    Office   Device
-----   ------   ------- 
USR-A    LA-HQ    MACBOOK
USR-B    LA-HQ    MACBOOK
USR-A    LA-HQ    IMAC
USR-B    NY-HQ    IMAC
USR-B    NY-HQ    IPHONE

我希望数据如下所示

Name    Office   Device
-----   ------   ------- 
USR-A    LA-HQ    MACBOOK, IMAC
USR-B    LA-HQ    MACBOOK
USR-B    NY-HQ    IMAC, IPHONE

2 个答案:

答案 0 :(得分:1)

使用纯Ruby相当容易,这可能比尝试使用SQL容易。这可以帮助您入门:

require 'ostruct'

rows = [
  OpenStruct.new(name: 'USR-A', office: 'LA-HQ', device: 'MACBOOK'),
  OpenStruct.new(name: 'USR-B', office: 'LA-HQ', device: 'MACBOOK'),
  OpenStruct.new(name: 'USR-A', office: 'LA-HQ', device: 'IMAC'),
  OpenStruct.new(name: 'USR-B', office: 'NY-HQ', device: 'IMAC'),
  OpenStruct.new(name: 'USR-B', office: 'NY-HQ', device: 'IPHONE'),
]

groups = rows.group_by { |i| "#{i.name}#{i.office}" }.values
groups = groups.map do |group|
  device = group.map(&:device).join(", ")
  OpenStruct.new(
    name: group.first.name,
    office: group.first.office,
    device: device
  )
end
p groups

=> [#<OpenStruct name="USR-A", office="LA-HQ", device="MACBOOK, IMAC">,
    #<OpenStruct name="USR-B", office="LA-HQ", device="MACBOOK">,
    #<OpenStruct name="USR-B", office="NY-HQ", device="IMAC, IPHONE">]

答案 1 :(得分:1)

使用PostgreSQL的一种简单方法是使用array_agg

ms = Model.select('"Name", "Office", array_agg("Device") as "Devices"').group(:Name, :Office)

这将为您提供Model中的ms个,并且每个都将有一个额外的Devices方法,该方法将为您提供设备字符串数组。

或者您可以使用string_agg

ms = Model.select('"Name", "Office", string_agg("Device", ',') as "Devices"').group(:Name, :Office)

Devices方法将为您提供字符串而不是数组。

这两个方法都不能保证聚合的任何特定顺序,但是如果需要,您可以specify the order

array_agg("Device" order by "Device")
string_agg("Device", ',' order by "Device" desc)