我的模型 var hideLogin = true ;
$('#ModalHelpLogin').on('shown.bs.modal', function (e) {
hideLogin = false ;
})
$('#ModalHelpLogin').on('hidden.bs.modal', function (e) {
hideLogin = true ;
})
$('#DropLogin').on('hide.bs.dropdown', function () {
return hideLogin ;
});
包含Company
,pbr
和market_cap
列。
要获得按category
分组的pbr
的平均值,我可以使用category
方法。
group
但是没有加权平均法。
要获得加权平均值,我需要运行此SQL代码。
Company.group(:category).average(:pbr)
在select case when sum(market_cap) = 0 then 0 else sum(pbr * market_cap) / sum(market_cap) end as weighted_average_pbr, category AS category FROM "companies" GROUP BY "companies"."category";
中,此查询可以正常运行。但我不知道如何使用Rails。
psql
返回错误:
sql = %q(select case when sum(market_cap) = 0 then 0 else sum(pbr * market_cap) / sum(market_cap) end as weighted_average_pbr, category AS category FROM "companies" GROUP BY "companies"."category";)
ActiveRecord::Base.connection.select_all(sql)
最好是我可以扩展Rails方法,以便我可以使用
output error: #<NoMethodError: undefined method `keys' for #<Array:0x007ff441efa618>>
但我听说扩展rails查询有点蠢,现在我只想知道如何从Rails运行sql的结果。
有谁知道怎么做?
rails:4.2.1
答案 0 :(得分:1)
您使用的是什么版本的Rails?我没有得到Rails 4.2的错误。在Rails 3.2中select_all
用于返回Array
和in 4.2,它返回ActiveRecord::Result
。但在任何一种情况下,没有keys
方法是正确的。相反,您需要在keys
或Array
的每个元素上调用Result
。听起来问题不是来自运行查询,而是来自你之后正在做的事情。
在任何情况下,为了获得您所描述的更流畅的方法,您可以这样做:
class Company
scope :weighted_average, lambda{|col|
select("companies.category").
select(<<-EOQ)
(CASE WHEN SUM(market_cap) = 0 THEN 0
ELSE SUM(#{col} * market_cap) / SUM(market_cap)
END) AS weighted_average_#{col}
EOQ
}
这将让您说Company.group(:category).weighted_average(:pbr)
,您将获得Company
个实例的集合。每个人都有一个额外的weighted_average_pbr
属性,所以你可以这样做:
Company.group(:category).weighted_average(:pbr).each do |c|
puts c.weighted_average_pbr
end
这些实例不具有正常属性,但它们将具有category
。这是因为它们不代表单个公司,而是代表具有相同category
的公司组。如果要按其他方式分组,可以参数化lambda以获取分组列。在这种情况下,您也可以将group
调用移动到lambda中。
现在被警告,weighted_average
的参数直接进入您的SQL查询而不转义,因为它是一个列名。因此,请确保您没有将用户输入传递给该方法,否则您将遇到SQL注入漏洞。事实上,我可能会在lambda中放一个警卫,比如raise "NOPE" unless col =~ %r{\A[a-zA-Z0-9_]+\Z}
。
更一般的教训是,您可以使用select
包含额外的SQL表达式,并让Rails神奇地将它们视为从查询返回的实例上的属性。
另请注意,与select_all
不同的是,您获得了大量哈希值,使用此方法可以获得大量Company
个实例。所以再没有keys
方法! : - )