I think there is a misunderstanding going on here. relation.count will always perform a count on database, it won't load every row in our ruby process:
(main) normal> u = User.group(:profile_id); u.count (0.4ms) SELECT COUNT(*) AS count_all, profile_id AS profile_id FROM "users" GROUP BY profile_id => {1=>4, 2=>1} (main) normal> u.count (0.4ms) SELECT COUNT(*) AS count_all, profile_id AS profile_id FROM "users" GROUP BY profile_id => {1=>4, 2=>1} (main) normal> u.count.values.sum (0.3ms) SELECT COUNT(*) AS count_all, profile_id AS profile_id FROM "users" GROUP BY profile_id => 5 Performing u.count.values.sum will also perform a grouped count and just sum the quantity of rows for every key. On Mon, Sep 15, 2014 at 8:57 AM, G. Sobrinho <gabriel.sobri...@gmail.com> wrote: > That's the point, relation.count will *always* perform a COUNT on database. > > On Mon, Sep 15, 2014 at 8:50 AM, Will Bryant <will.bry...@gmail.com> > wrote: > >> Yes, but it will have to *load* all the rows from the database into ruby. >> If we have a table with a few million of rows, which is pretty small for a >> real app, and we're doing a join and a group to get the count of some >> associated record, then calling .values.sum would load all those millions >> of rows, and then add up the values. >> >> Returning the millions of rows (even if it was just the IDs and counts) >> is many orders of magnitude slower than getting the database to tell us how >> many rows would be in the rowset, and it's going to use a lot of memory too. >> >> Yes, if your app only has thousands of rows, then it won't matter. But >> this is not a good argument for a database library to be inefficient. >> >> The point is that count should always return a count of the results in a >> relation, irrespective of what is involved in the relation. That's the >> point of relational algebra; you can combine two operations and you get the >> logical composite. >> >> Returning the count of each grouping is a logically separate thing to do, >> and it should have a separate API call. >> >> >> On 15/09/2014, at 23:36 , G. Sobrinho <gabriel.sobri...@gmail.com> wrote: >> >> I'm not sure if you get what .values.sum would do: >> >> c = User.group(:role).count >> => {:normal=>3, :admin=>4} >> >> c.values.sum >> => 7 >> >> >> Even a hash with thousands of keys/values would sum its values very fast. >> >> >> And I don't get what you mean with "is actually changing what would be >> counted". >> >> Considering c = User.group(:role).count, c.values.sum would return the >> exactly number of records that would be returned and c.keys.sum would >> return exactly number of group param that would be returned, no? >> >> On Sun, Sep 14, 2014 at 2:20 AM, Will Bryant <will.bry...@gmail.com> >> wrote: >> >>> Calling .values.sum might have to load a LOT of (id, count) rows so it >>> isn't a very scalable solution. >>> >>> Calling regroup or something is actually changing what would be counted >>> - the group can affect the count, especially if you use HAVING clauses. >>> >>> There's nothing wrong with having the grouped count functionality, but >>> it's messing up the #count API IMHO. >>> >>> >>> On 13/09/2014, at 03:40 , Gabriel Sobrinho <gabriel.sobri...@gmail.com> >>> wrote: >>> >>> I'm against to count and size works equally since I would want to know >>> how many grouped records do I have (i.e.: how many roles do I have on >>> determining relation). >>> >>> I think that count and size is working as both should. >>> >>> >>> Although, if you want to count all records of a grouped relation, you >>> have to remove the group or just sum the counts: >>> >>> User.count >>> >>> >>> or: >>> >>> >>> >>> User.group(:role).count.values.sum >>> >>> >>> Not elegant but if you can't remove the group for that count, you have >>> to do that. >>> >>> >>> One possible option would rails have something like regroup(false) as >>> reorder(false), but again I think that just adding the values is more >>> easier for everyone :) >>> >>> On Thursday, September 11, 2014 11:54:14 PM UTC-3, Shinohara Teruki >>> wrote: >>>> >>>> >> size in this case is an pretty much an "alias" for count, thus it's >>>> gonna work the same way as count when grouping. >>>> >>>> I think that current #size don't behave like an alias for #count. >>>> >>>> g = User.group(:role); g.load; g.count >>>> => {:normal=>3, :admin=>4} >>>> >>>> g = User.group(:role); g.load; g.size >>>> => 2 >>>> >>>> When I call #load before #count or #size, a return value of #count >>>> don't equals to a return value of #size. >>>> >>>> >>>> >> Is there any particular reason to know how many records returned if >>>> you are grouping? >>>> >>>> I expect #count and #size to return same value. >>>> It is not the case that I want to know how many records the grouping >>>> query returns. >>>> >>>> My ideal implementation: >>>> >>>> g = User.group(:role); g.load; g.count >>>> => {:normal=>3, :admin=>4} >>>> >>>> g = User.group(:role); g.load; g.size >>>> =>{:normal=>3, :admin=>4} >>>> >>>> or >>>> >>>> g = User.group(:role); g.load; g.count >>>> => 2 >>>> >>>> g = User.group(:role); g.load; g.size >>>> =>2 >>>> >>>> What do you think? >>>> >>>> Thank you >>>> >>>> >>>> 2014年9月12日金曜日 8時21分39秒 UTC+9 Carlos Antonio da Silva: >>>>> >>>>> size in this case is an pretty much an "alias" for count, thus it's >>>>> gonna work the same way as count when grouping. >>>>> >>>>> Is there any particular reason to know how many records returned if >>>>> you are grouping? >>>>> >>>>> On Wed, Sep 10, 2014 at 11:16 AM, Shinohara Teruki <ts....@gmail.com> >>>>> wrote: >>>>> >>>>>> ActiveRecord::Relation.size returns a Hash when I use a group method. >>>>>> I think that a size method is expected to return integer typically. >>>>>> >>>>>> I propose this implementation: >>>>>> >>>>>> def size >>>>>> if loaded? >>>>>> @records.length >>>>>> else >>>>>> count_value = count(:all) >>>>>> count_value.is_a?(Hash) ? count_value.length : count_value >>>>>> end >>>>>> end >>>>>> >>>>>> This is a current implementation: >>>>>> >>>>>> # https://github.com/rails/rails/blob/master/activerecord/lib/active_ >>>>>> record/relation.rb >>>>>> # Returns size of the records. >>>>>> def size >>>>>> loaded? ? @records.length : count(:all) >>>>>> end >>>>>> >>>>>> >>>>>> A count method is implemented on calculations.rb. >>>>>> https://github.com/rails/rails/blob/master/activerecord/lib/active_ >>>>>> record/relation/calculations.rb >>>>>> >>>>>> >>>>>> What do you think? >>>>>> >>>>>> Thank you >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "Ruby on Rails: Core" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to rubyonrails-co...@googlegroups.com. >>>>>> To post to this group, send email to rubyonra...@googlegroups.com. >>>>>> Visit this group at http://groups.google.com/group/rubyonrails-core. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> At. >>>>> Carlos Antonio >>>>> >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to rubyonrails-core+unsubscr...@googlegroups.com. >>> To post to this group, send email to rubyonrails-core@googlegroups.com. >>> Visit this group at http://groups.google.com/group/rubyonrails-core. >>> For more options, visit https://groups.google.com/d/optout. >>> >>> >>> >>> -- >>> You received this message because you are subscribed to a topic in the >>> Google Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this topic, visit >>> https://groups.google.com/d/topic/rubyonrails-core/2BELBVaNEeA/unsubscribe >>> . >>> To unsubscribe from this group and all its topics, send an email to >>> rubyonrails-core+unsubscr...@googlegroups.com. >>> To post to this group, send email to rubyonrails-core@googlegroups.com. >>> Visit this group at http://groups.google.com/group/rubyonrails-core. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> >> >> -- >> Cheers, >> >> Gabriel Sobrinho >> http://gabrielsobrinho.com/ >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to rubyonrails-core+unsubscr...@googlegroups.com. >> To post to this group, send email to rubyonrails-core@googlegroups.com. >> Visit this group at http://groups.google.com/group/rubyonrails-core. >> For more options, visit https://groups.google.com/d/optout. >> >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "Ruby on Rails: Core" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/rubyonrails-core/2BELBVaNEeA/unsubscribe >> . >> To unsubscribe from this group and all its topics, send an email to >> rubyonrails-core+unsubscr...@googlegroups.com. >> To post to this group, send email to rubyonrails-core@googlegroups.com. >> Visit this group at http://groups.google.com/group/rubyonrails-core. >> For more options, visit https://groups.google.com/d/optout. >> > > > > -- > Cheers, > > Gabriel Sobrinho > http://gabrielsobrinho.com/ > -- Cheers, Gabriel Sobrinho http://gabrielsobrinho.com/ -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-core+unsubscr...@googlegroups.com. To post to this group, send email to rubyonrails-core@googlegroups.com. Visit this group at http://groups.google.com/group/rubyonrails-core. For more options, visit https://groups.google.com/d/optout.