2014-05-11 87 views
0

我可以運行任何SQL,並將結果作爲列的散列或者a set of Postgres tuples(包含每個元組的散列)。枚舉Ruby中的Postgres結果集

我不確定如何使用Postgres結果集,尤其是以慣用的類Ruby方式工作。

這是我的代碼:

sql = "select status, count(*) from batch_details where batch_id = 950 group by status" 
status_counts = ActiveRecord::Base.connection.execute(sql) 

我要重複,雖然結果集,並通過名稱來訪問每個元素:

status_counts.each do |st| 
    puts st 
    puts st['count'] 
end 

{"status"=>"new", "count"=>"2"} 
2 
{"status"=>"ready", "count"=>"23"} 
23 
{"status"=>"processing", "count"=>"177"} 
177 
{"status"=>"complete", "count"=>"50"} 
50 
{"status"=>"error", "count"=>"50"} 
50 

這是不可能的結果集到一個數組轉換的散列:

2.1.1 :031 > arr = status_counts.to_array 
NoMethodError: undefined method `to_array' for #<PG::Result:0x000000097f17b0> 

試圖將結果集轉換爲哈希散列的相同事情:

2.1.1 :032 > hsh = status_counts.to_hash 
NoMethodError: undefined method `to_hash' for #<PG::Result:0x000000097f17b0> 

我想:

  • 運行通過查詢數據庫
  • 一個分組對抗(大)確定%處理排除某些值

使用哈希值完成上面,我想排除'新'和'準備'狀態,加起來除以總數:

(177 + 50 + 50/2 + 23 + 177 + 50 + 50) * 100 

我迄今爲止代碼:

status_counts.each {|st| total += st['count'].to_i} => works 

但它不工作:

status_counts.each do |st| 
    ['processing','complete','error'].include? st['status'] do 
     total2 += st['count'].to_i 
    end 
end 

pct = total2/total * 100 
  • 我怎樣才能與Postgres的更容易造成集工作?
  • 如何在「Ruby方式」中執行此任務?
+1

'PG :: Result'有一個'to_a'方法,而不是一個'to_array'方法。如果你願意,你可以將整個計算推入數據庫,Rails的人可能會反對,但這是正確的。 –

+0

我原本以爲將整個calc推入數據庫,但表格非常大,一旦檢索到初始數據集,我認爲用ruby運行它會更有效率。在列上執行復雜的數學運算時,SQL不使用索引。無論如何,我想更好地理解PG :: Result結構。我會研究to_a。謝謝! – ardochhigh

+0

如果你不使用Rails(或者不迷戀ActiveRecord),我強烈推薦使用[Sequel](http://sequel.jeremyevans.net)。這是一個寫得很好的ORM,可以生成很好的SQL。作者使用PostgreSQL數據庫作爲他的主DBM,所以Sequel非常適合它。 –

回答

2

也許是這樣?:

status_counts. 
    select { |tuple| %w(processing complete error).include?(tuple['status']) }. 
    inject(0) { |memo, tuple| memo += tuple['count'].to_i } 

第一步過濾結果集以獲得期望的元組;第二步是從選定的元組中總結計數。 PGResult在Enumerable中混合使用,因此它應該在select/inject中使用。

+0

看起來很棒!我會在今天晚些時候嘗試。 – ardochhigh

0

沒有一個確切的答案,以我自己的問題,但任何人試圖重複一個Postgres結果集的有用信息:

sql = "update batch_details set status = 'processing' " + 
     "where status in ('ready','processing','failed') " + 
     "and batch_id = #{batch_id} " + 
     "returning id" 
batch_detail_ids = [] 
res = ActiveRecord::Base.connection.execute(sql) 
# TODO needs some error checking 
res.each{|tuple| batch_detail_ids << tuple['id'].to_i}