ActiveRecord Count 用于计算 Rails 中 group by 返回的行数
我环顾四周,找不到任何答案。所有答案都涉及未使用 GROUP BY 的计数。
背景: 我有一个分页器,它将采用 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)
使用 :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
如您所见只是将 COUNT() 包裹在“tags.*, 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(*)
它返回整个 GROUP BY 结果集,而不是行数。
有没有办法解决这个问题,或者我是否必须破解分页器来解释 GROUP BY 的查询(以及我将如何去做)?
I looked around and couldn't find any answers to this. All answers involved counts that did not use a GROUP BY.
Background:
I have a paginator that will take options for an ActiveRecord.find. It adds a :limit and :offset option and performs the query. What I also need to do is count the total number of records (less the limit), but sometimes the query contains a :group option and ActiveRecord.count tries to return all rows returned by the GROUP BY along with each of their counts. I'm doing this in Rails 2.3.5.
What I want is for ActiveRecord.count to return the number of rows returned by the GROUP BY.
Here is some sample code that demonstrates one instance of this (used for finding all tags and ordering them by the number of posts with that tag):
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)
With the :select option, the Tag.count generates the following 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
As you can see it merely wrapped a COUNT() around the 'tags.*, COUNT(*)', and MySQL complains about the COUNT within a COUNT.
Without the :select option, it generates this SQL:
SELECT count(*) AS count_all, tags.id AS tags_id FROM `tags` INNER JOIN posts_tags GROUP BY tags.id ORDER BY COUNT(*)
which returns the whole GROUP BY result set and not the number of rows.
Is there a way around this or will I have to hack up the paginator to account for queries with GROUP BYs (and how would I go about doing that)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
似乎您需要单独处理分组查询。在没有组的情况下进行计数会返回一个整数,而在有组的情况下进行计数会返回一个哈希值:
Seems like you'd need to handle the grouped queries separately. Doing a count without a group returns an integer, while counting with a group returns a hash:
如果您使用的是 Rails 4 或 5,您也可以执行以下操作。
If you're using Rails 4 or 5 you can do the following as well.
我的情况的解决方法似乎是替换 :group => 'tags.id' 与 :select =>在执行计数之前选项哈希中的“DISTINCT Tags.id”。
The workaround for my situation seems to be to replace the :group => 'tags.id' with :select => 'DISTINCT tags.id' in the options hash before executing the count.
另一个(hacky)解决方案:
Another (hacky) solution:
如果我正确理解你的问题,那么如果你根本不使用 Tag.count ,它应该可以工作。在您的选择哈希中指定“COUNT(*) AS post_count”就足够了。例如:
如您所见,查询中的 post_count 值可以从 @tag 实例访问。如果你想获取所有标签,那么也许是这样的:
更新:
可以使用要计数的属性和参数 :distinct 来调用 Count
If I understand your question correctly, then it should work if you don't use Tag.count at all. Specifying 'COUNT(*) AS post_count' in your select hash should be enough. For example:
As you can see, the post_count value from the query is accessible from the @tag instance. And if you want to get all tags, then perhaps something like this:
Update:
Count can be called with which attribute to count and also a parameter :distinct