Sql Activerecord将具有相同列值的行合并为一行

Sql Activerecord将具有相同列值的行合并为一行,sql,ruby,activerecord,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 -----

在我的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

使用普通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">]
需要“ostruct”
行=[
OpenStruct.new(名称:“USR-A”,办公室:“LA-HQ”,设备:“MACBOOK”),
OpenStruct.new(名称:“USR-B”,办公室:“LA-HQ”,设备:“MACBOOK”),
OpenStruct.new(名称:“USR-A”,办公室:“LA-HQ”,设备:“IMAC”),
OpenStruct.new(名称:“USR-B”,办公室:“NY-HQ”,设备:“IMAC”),
OpenStruct.new(名称:“USR-B”,办公室:“NY-HQ”,设备:“IPHONE”),
]
groups=rows.group_by{i}“{i.name}{i.office}.值
groups=groups.map do | group|
device=group.map(&:device.join(“,”)
OpenStruct.new(
名称:group.first.name,
办公室:集团第一办公室,
设备:设备
)
终止
p群
=> [#,
#,
#]

使用普通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">]
需要“ostruct”
行=[
OpenStruct.new(名称:“USR-A”,办公室:“LA-HQ”,设备:“MACBOOK”),
OpenStruct.new(名称:“USR-B”,办公室:“LA-HQ”,设备:“MACBOOK”),
OpenStruct.new(名称:“USR-A”,办公室:“LA-HQ”,设备:“IMAC”),
OpenStruct.new(名称:“USR-B”,办公室:“NY-HQ”,设备:“IMAC”),
OpenStruct.new(名称:“USR-B”,办公室:“NY-HQ”,设备:“IPHONE”),
]
groups=rows.group_by{i}“{i.name}{i.office}.值
groups=groups.map do | group|
device=group.map(&:device.join(“,”)
OpenStruct.new(
名称:group.first.name,
办公室:集团第一办公室,
设备:设备
)
终止
p群
=> [#,
#,
#]

使用PostgreSQL的简单方法是:

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

或者您可以使用
string\u agg

ms = Model.select('"Name", "Office", string_agg("Device", ',') as "Devices"').group(:Name, :Office)
设备
方法将为您提供字符串而不是数组

这两种方法都不能保证聚合的任何特定顺序,但如果需要,您可以:

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

PostgreSQL的一个简单方法是使用:

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

或者您可以使用
string\u agg

ms = Model.select('"Name", "Office", string_agg("Device", ',') as "Devices"').group(:Name, :Office)
设备
方法将为您提供字符串而不是数组

这两种方法都不能保证聚合的任何特定顺序,但如果需要,您可以:

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

您的想法是在每次提取后操作数据,或者需要将数据重写到数据库中?您使用的是哪个数据库?@muistooshort我使用的是postgresDB@iGian不,我不需要将数据重写回数据库。为了提高速度,我希望在数据库端进行数据操作。您的想法是在每次提取后操作数据,或者需要将数据重写到数据库中?您使用的是哪个数据库?@muistooshort我使用的是postgresDB@iGian不,我不需要将数据重写回数据库。我想在数据库端的数据操作速度。谢谢你的回答。出于性能原因,我想在数据库方面这样做。谢谢你的回答。出于性能原因,我想在数据库方面这样做。谢谢您的回答。这正是我需要的。谢谢你的回答。这正是我需要的。