2011-02-01 6 views
2

私は列のテーブルを持っていますname, duration, type, ref_id配列操作(特定のグループで1つの列を合計し、他の列を同じに保ちます)

私はしょっちゅうので、おそらくそれは名前の['bill', 'bob', 'bob', 'jill']のCOLのように見える、と期間[3, 5, 6, 2]、およびタイプの['man', boy', 'boy', 'girl']、およびref_idため[1, 2, 2, 3]ますテーブルを更新します。

私はこのようになりますハッシュまたは何かを得るように、私はすべての期間を追加できるように私のテーブルを操作したいと思います:

{'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)として名前を与えています。 、2)しかし、私は残りのデータを失う...)

私は手動で各ログを通過し、名前/型/ ref_idを追加することができますそれがハッシュにない場合は、 。もしそうなら、それをする最善の方法は何ですか?

レール配列の操作/よく使用されるイディオムに関する良い情報がある場合は、それも素晴らしいでしょう!

答えて

2

最初のカップル。

テーブルが正しく正規化されていません。このテーブルを(少なくとも)2つに分割する必要があります。usersdurationsです。リレーショナルデータベースの多くの理由でこれを行う必要があります。

また、結果として必要なハッシュも正しく表示されないため、プレゼンテーションに合わせてデータを事前にグループ化していることを示します。配列のハッシュよりも、これらの結果をハッシュの配列に入れるのは、通常は論理的です。

今の答えに:これを変換するために

durations = Log.find(:all, 
    :select => 'name, type, ref_id, SUM(duration) as duration', 
    :group => 'name, type, ref_id' 
) 

SELECT name, type, ref_id, SUM(duration) as duration 
FROM logs 
GROUP BY name, type, ref_id 

や、ARを使用して:

あなたのテーブルでは、あなたは単にGROUP BYを行うことができます配列のハッシュは、次のようなものを使用します。

+0

まあまあ「名前」は本当にログ名ですが、私はそれがより簡単かもしれないと思ったので、ここに人々の名前を付けました。あなたが望むハッシュはどのように見えますか? (これは私にとって最も直感的な感覚を作りました)。私は実際にいくつかのグラフを作成するためにこのデータを取得しています(私が使用しているプラ​​グインは、プロットするために値の配列を取り、x値のために別の配列をとる)ので、ハッシュの配列がうまくいくかどうかはわかりません。 (あなたはどういう意味ですか?)しかし、これをどうやってやってくれてありがとう、素晴らしい作品です! (私はどちらかの前にデータベースで作業していませんでした) – butterywombat

+0

通常、 'find'メソッドが返すものからデータを変換する理由はありません。必要な部分だけを使用してください(通常はビュー内)。一連の名前が必要な場合は、 'durations.map {| d | d.name} 'などとなります。 –

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 
+0

hmmはハッシュを行います['duration'] << l.durationはデュレーションを累積しますか?私は各ログ名の期間を集計しています。 btw、私はレコードを保存することについて考えていない...私はちょうどこれが発生するたびに、新しい累積ログの期間を保存し、個々のレコードを削除することができたと思います。これはより良いデザインでしょうか? – butterywombat

+0

@butterywombatいいえ、この解決策は 'duration'値を合計しません。 – Phrogz

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)呼び出しを行うことです。

関連する問題