我有一个包含name, duration, type, ref_id
列的日志表。
我经常更新表格,所以它可能看起来像['bill', 'bob', 'bob', 'jill']
列表中的名称,[3, 5, 6, 2]
表示持续时间,['man', boy', 'boy', 'girl']
表示类型,[1, 2, 2, 3]
} for ref_id。
我想操纵我的表,以便我可以添加所有持续时间,以便我得到一个哈希或类似的东西:
{'name' => ['bill', 'bob', 'jill'], 'duration' => [3, 11, 2], 'type' => ['man', 'boy', 'girl'], ref_id => [1, 2, 3]}
我该怎么做?
(更多信息 - 目前我正在做Log.sum(:duration, :group => 'name')
,它给我的名字本身就是键(bill,bob,jill)而不是列名,正确的持续时间总和作为它们的值( 3,11,2)。但随后我丢失了剩下的数据......)
我想我可以手动浏览每个日志并添加名称/类型/ ref_id,如果它不在哈希值中,则添加到持续时间。如果是这样,最好的方法是什么?
如果你知道有关rails数组操作/常用习语的好消息来源,那也会很棒!
答案 0 :(得分:2)
首先注意几个笔记。
您的表格未正确规范化。您应该将此表拆分为(至少)两个:users
和durations
。你应该这样做有很多原因,那就是关系数据库101.
此外,您想要的哈希值看起来也不正确,它表明您正在预先分组数据以适合您的演示文稿。将这些结果放在哈希数组中通常比在数组哈希中更合乎逻辑。
现在回答:
使用您的表格,您只需执行GROUP BY:
SELECT name, type, ref_id, SUM(duration) as duration
FROM logs
GROUP BY name, type, ref_id
或使用AR:
durations = Log.find(:all,
:select => 'name, type, ref_id, SUM(duration) as duration',
:group => 'name, type, ref_id'
)
为了将其转换为数组的哈希值,您可以使用类似:
的内容Hash[
%w{name, type, ref_id, duration}.map{|f|
[f, durations.map{|h|
h.attributes[f]
}]
}
]
答案 1 :(得分:1)
也许您需要的是这样的东西,它会旋转所有日志条目并收集结果:
# Define attributes we're interested in
operate_on = %w[ name duration type ref_id ]
# Create a new hash with placeholder hashes to collect instances
summary = Hash[operate_on.map { |k| [ k, { } ] }]
Log.all.collect do |log|
operate_on.each do |attr|
# Flag this attribute/value pair as having been seen
summary[attr][log.send(attr)] = true
end
end
# Extract only the keys, return these as a hash
summary = Hash[summary.map { |key, value| [ key, value.keys ] }]
一种更有效的方法是将此作为几个SELECT DISTINCT(x)
调用,而不是实例化这么多模型。
答案 2 :(得分:0)
如果您想要从哈希中保存记录,或者您想要查询表并以此形式返回结果,则不太明白。如果你想得到一个哈希值,那么这应该可行:
Log.all.inject({}) do |hash, l|
hash['name'] ||= []
hash['duration'] ||= []
hash['type'] ||= []
hash['ref_id'] ||= []
hash['name'] << l.name
hash['duration'] << l.duration
hash['type'] << l.type
hash['ref_id'] << l.ref_id
hash
end