使用Rails 4 Activerecord将多个列计数合并到单个查询中

Rails 4.1,Postgres 9.3,部署到Heroku

我正在尝试减少对数据库的调用次数。

我有一个大表,调查,有多个布尔列,如role_composerrole_performer等。

控制器有多个查询,如

 @sample = Survey.where(...whatever...) @Composers = @sample.count("case when role_composer then true end") ... @Performers = @sample.count("case when role_performer then true end") 

这样可以正常工作,但会导致对数据库的许多单独查询只有select中的表达式不同。 有没有办法将此构造为一个具有多个聚合/计算列的查询? 我也有使用average()和表达式的查询,但最常见的是count()。

在postgres中,这有效:

 SELECT count(case when role_composer then true end) as "COMPOSERS", count(case when role_performer then true end) as "PERFORMERS" from surveys; 

使用@sample上的Activerecord方法而不是求助于find_by_sql()的任何方法吗?

我尝试了各种方法但没有成功: .count().count() .select("count(...) as col1, count(...) as col2") .count([array]) .select("count(...) as col1, count(...) as col2") .select(["count(...) as col1", "count(...) as col2"])

提前感谢您的任何答案。

如果你记住两件事.select("count(...) as col1, count(...) as col2")你的.select("count(...) as col1, count(...) as col2")版本应该可以正常工作:

  1. M.where(...).select(...)返回多个东西,即使查询只返回一行。
  2. 仅仅因为inspect输出中没有出现的东西并不意味着它不存在。

你正在做没有GROUP BY的聚合,所以你只能得到一行。 要解开该行,您可以first说:

 counts = Survey.where(...) .select('count(case when role_composer then true end) as composers, count(case when role_performer then true end) as performers') .first 

这将为您提供countsSurvey实例。 如果你在控制台中查看这些counts ,你会看到如下内容:

 # 

inspect输出仅包含列中的值(即Survey类知道的内容),但composersperformers将在那里。 但是,由于ActiveRecord不知道它们应该是什么类型,它们将作为字符串:

 composers = counts.composers.to_i performers = counts.performers.to_i 

如果去寻找它,你select所有东西都会在那里。