表连接sql到rails活动记录查询

如何将以下内容转换为活动记录查询:

SELECT reviews.style_id, AVG("col1"), AVG("col2") FROM reviews, audios WHERE reviews.consumer_id = audios.consumer_id GROUP BY style_id; 

col1col2属于audios表,但它们是唯一命名的( reviews没有类似的列名),因此没有歧义错误。

我正在使用PostgreSQL。

如果您在ReviewAudio之间有关联,那么这样的事情:

 revs = Review.joins(:audios) .group('style_id') .select('style_id, avg(col1) as avg_col1, avg(col2) as avg_col2') 

这将给出revs中的Review实例列表,这些实例将有额外的avg_col1avg_col2方法来访问平均值以及通常的style / style_id方法,但Review通常会提供的其他列访问器方法将引发exception。

如果您没有设置关联,则可以手动执行JOIN:

 revs = Review.joins('join audios on reviews.consumer_id = audios.consumer_id') .group('style_id') .select('style_id, avg(col1) as avg_col1, avg(col2) as avg_col2') 

如果您只需要原始数据而没有所有ActiveRecord包装和开销,那么您可以执行原始SQL并使用select_rows手动进行哈希化:

 Review.connection.select_rows(%q{ select r.style_id, avg(a.col1), avg(a.col2') from reviews r join audios a on r.consumer_id = a.consumer_id group by r.style_id }).map do { :style_id => r.shift, :avg_col1 => r.shift.to_f, :avg_col2 => r.shift.to_f } end 

这会给你一个哈希数组。 您甚至可以使用Struct来创建简单的数据包装类来简化该方法:

 c = Struct.new(:style_id, :avg_col1, :avg_col2) revs = Review.connection.select_rows(%q{...}).map do |r| c.new(r.shift, r.shift.to_f, r.shift.to_f) end 

PS:不要在SQL中使用隐式连接条件,这只是生成交叉产品的一种快速简便的方法,使用显式连接条件:

 SELECT ... FROM reviews JOIN audios ON reviews.consumer_id = audios.consumer_id GROUP BY style_id