在.each循环中组合ActiveRecord :: Result

时间:2016-03-03 21:54:55

标签: ruby-on-rails arrays activerecord

我现在有这个工作,但必须有一个更好的方法。我有一个模型,我在其中查询外部oracle DB视图。在这种特殊情况下,我必须为每个id值运行一个查询,并将这些结果组合成一个数组。

这样可行但是,它需要对Array进行相当多的维护才能以更易于使用的格式获取信息。希望有一种简化方法:

def self.count_by_year(ids, year)
    start_date = DateTime.strptime(year.to_s, "%Y").strftime("%Y%m%d")
    end_date = DateTime.strptime(year.to_s, "%Y").end_of_year.strftime("%Y%m%d")
    bulk_issues = []
    if ids.size > 1
      ids.each do |uc|
        bulk_issues << (External.connection.select_all "SELECT COUNT(*) FROM DB WHERE ID='#{uc.id}' AND GROUP_NAME != 'CA' AND STATUS != 'Cancelled' AND (DATE_OPENED BETWEEN '#{start_date}' AND '#{end_date}')")
      end
    else
      bulk_issues << (External.connection.select_all "SELECT COUNT(*) FROM DB WHERE ID='#{ids.first.id}' AND GROUP_NAME != 'CA' AND STATUS != 'Cancelled' AND (DATE_OPENED BETWEEN '#{start_date}' AND '#{end_date}')")
    end
    return bulk_issues
  end

调用时返回以下内容:

[#<ActiveRecord::Result:0x007fdafd95ec20 @columns=["count(*)"], @rows=[[51]], @hash_rows=nil, @column_types={}>, #<ActiveRecord::Result:0x007fdafd95d320 @columns=["count(*)"], @rows=[[19]], @hash_rows=nil, @column_types={}>]

当展平时,它会返回:

[{"count(*)"=>51}, {"count(*)"=>19}]

将数据拉出来是一件痛苦的事情,因为我必须将值拉出并将它们放入一个新的数组中,以便将其格式化为我使用的值。

我要做的是让函数返回数组中的数据,如下所示:

[51, 19]

对此的任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

嗯,首先,Oracle supports IN expressions,而不是ids.each...而不是:

bulk_issues = External.connection.select_all "SELECT COUNT(*) FROM DB WHERE ID IN (#{ids.map{|id| "'#{id.id}'"}.join(",")}) AND GROUP_NAME != 'CA' AND STATUS != 'Cancelled' AND (DATE_OPENED BETWEEN '#{start_date}' AND '#{end_date}')"

那么这不是一个数组,它只是一个类似{"count(*)"=>70}的哈希值,所以只能从70中获取该号码:

*, count = bulk_issues.first

因此,在您的查询中添加AS,以便我们可以确定我们的哈希将返回什么,整个方法变为:

def self.count_by_year(ids, year)
  start_date = DateTime.strptime(year.to_s, "%Y").strftime("%Y%m%d")
  end_date = DateTime.strptime(year.to_s, "%Y").end_of_year.strftime("%Y%m%d")

  res = External.connection.select_all("SELECT COUNT(*) AS count FROM DB WHERE ID IN (#{ids.map{|id| "'#{id.id}'"}.join(",")}) AND GROUP_NAME != 'CA' AND STATUS != 'Cancelled' AND (DATE_OPENED BETWEEN '#{start_date}' AND '#{end_date}')")

  return res.to_hash.first['count'].to_i
end