ActiveRecord Count计算Rails中group by返回的行数

J.M*_*elo 19 activerecord ruby-on-rails ruby-on-rails-2

我环顾四周,找不到任何答案.涉及的所有答案都没有使用GROUP BY.

背景: 我有一个paginator,它将为ActiveRecord.find提供选项.它添加了:limit和:offset选项并执行查询.我还需要做的是计算记录总数(减去限制),但有时查询包含:group选项,ActiveRecord.count尝试返回GROUP BY返回的所有行及其每个计数.我在Rails 2.3.5中这样做.

我想要的是ActiveRecord.count返回GROUP BY返回的行数.

下面是一些示例代码,用于演示此实例(用于查找所有标记并按照标记的帖子数量排序):

options = { :select => 'tags.*, COUNT(*) AS post_count',
            :joins => 'INNER JOIN posts_tags',   #Join table for 'posts' and 'tags'
            :group => 'tags.id',
            :order => 'post_count DESC' }

@count = Tag.count(options)

options = options.merge { :offset => (page - 1) * per_page, :limit => per_page }

@items = Tag.find(options)
Run Code Online (Sandbox Code Playgroud)

使用:select选项,Tag.count生成以下SQL:

SELECT count(tags.*, COUNT(*) AS post_count) AS count_tags_all_count_all_as_post_count, tags.id AS tags_id FROM `tags`  INNER JOIN posts_tags  GROUP BY tags.id  ORDER BY COUNT(*) DESC
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,它只是在'tags.*,COUNT(*)'周围包裹了一个COUNT(),并且MySQL在COUNT中抱怨了COUNT.

如果没有:select选项,它会生成以下SQL:

SELECT count(*) AS count_all, tags.id AS tags_id FROM `tags` INNER JOIN posts_tags GROUP BY tags.id ORDER BY COUNT(*)
Run Code Online (Sandbox Code Playgroud)

它返回整个GROUP BY结果集而不是行数.

有没有办法解决这个问题,还是我必须破解分页器来解决GROUP BYs的问题(我将如何去做)?

zet*_*tic 23

您似乎需要单独处理分组查询.在没有组的情况下进行计数会返回一个整数,而使用组计数会返回一个哈希值:

Tag.count
  SQL (0.2ms)  SELECT COUNT(*) FROM "tags"
 => 37

Tag.count(:group=>"tags.id")
  SQL (0.2ms)  SELECT COUNT(*) AS count_all, tags.id AS tags_id FROM "tags" 
    GROUP BY tags.id
 => {1=>37}
Run Code Online (Sandbox Code Playgroud)


Dar*_*yne 16

如果您使用的是Rails 4或5,您也可以执行以下操作.

Tag.group(:id).count
Run Code Online (Sandbox Code Playgroud)


J.M*_*elo 9

我的情况的解决方法似乎是在执行计数之前用选项哈希中的:select =>'DISTINCT tags.id'替换:group =>'tags.id'.

count_options = options.clone
count_options.delete(:order)

if options[:group]
  group_by = count_options[:group]
  count_options.delete(:group)
  count_options[:select] = "DISTINCT #{group_by}"
end

@item_count = @type.count(count_options)
Run Code Online (Sandbox Code Playgroud)