On Aug 23, 7:18 pm, Sandy <[email protected]> wrote: > On Aug 23, 6:48 pm, Rob Biedenharn <[email protected]> > wrote: > > > > > On Aug 23, 2010, at 6:17 PM, Sandy wrote: > > > > On Aug 23, 5:05 pm, Rob Biedenharn <[email protected]> > > > wrote: > > >> On Aug 23, 2010, at 4:15 PM, Colin Law wrote: > > >>> On 23 August 2010 21:03, Bob Smith <[email protected]> wrote: > > >>>> in my models, household has_many :people and people > > >>>> has_one :household > > >>>> household has a name field, and people has household_id > > > >>> That should bepersonbelongs_to household. > > > >>>> the closest I got was: > > >>>> @test = Household.count:all, :group => > > >>>> 'people.household_id', :joins > > >>>> => :people > > > >>>> this does group the families together andcountthe members, > > >>>> but this has no way of including only families of one > > >>>> I am assuming that the output from this could be used to get the > > >>>> name > > >>>> field from households > > > >>> It might be worth looking at counter_cache. > > > >>> Colin > > > >> That might not be a bad idea (or even running a > > >> Household.connection.select_value on the SQL). > > > >> Well, the answer is going to be different for ActiveRecord 2.x and > > >> 3.0 > > > >> Here's how it would look in SQL > > > >> SELECTCOUNT(households.id) FROM households > > >> INNER JOIN people ON people.household_id = households.id > > >> GROUP BY households.id > > >> HAVINGCOUNT(people.id) = 1 > > > >> In AR 2.x, that's probably: > > > >> Household > > >> .count > > >> (:include > > >> = > > > >> :people > > >> , :group=>'households.id', :having=>'COUNT(people.id)=1').first.first > > > >> or since the join is simple and not truly needed: > > >>Person.count(:select => 'people.id', :group => > > >> 'people.household_id', :having => 'COUNT(id)=1').first.first > > > >> (the return will be an array of pairs [count,1] so [[count, > > >> 1]].first.first will becount) > > > >> And in AR 3.0, something like: > > > >> Household > > >> .select > > >> ('COUNT > > >> (households > > >> .id > > >> )').includes > > >> (:people > > >> ).group('households.id').having('COUNT(people.id)=1').to_a.size > > >> -or- > > >>Person > > >> .select > > >> ('COUNT(id)').group('household_id').having('COUNT(id)=1').to_a.size > > > >> You might be thinking "Hmm, ActiveRecord doesn't seem to be well > > >> suited for a query like this" > > > >> And I think you'd be right! > > > >> -Rob > > > >> Rob Biedenharn > > >> [email protected] http://AgileConsultingLLC.com/ > > >> [email protected] http://GaslightSoftware.com/- > > >> Hide quoted text - > > > >> - Show quoted text - > > > > As Colin (sort of) suggested, your Household model should contain > > > > has_many :people > > > > and yourPersonmodel should contain > > > > belongs_to :household > > > > Don't forget the colons, as shown above. > > > > Next, since the foregoing relationship will allow you to determine the > > > number of People in each Household, I would stay away from trying to > > > create an SQL statement, and, instead, allow the controller to provide > > > the appropriate array to your view, as follows: > > > > def single_person_household > > > households = Household.all > > > �...@households_with_one = Array.new > > > for h in households do > > > if h.people.count== 1.to_i > > > �...@households_with_one << h > > > end > > > end > > > end > > > But since Bob hasn't indicated the size of the Household andPerson > > data sets, I'd caution that performance of that code on a large number > > of households could be dismal as it has to first read every household > > into an object (i.e., memory) and then make a separate query to the > > database tocountthe persons. > > > Also, there's never a need to do 1.to_i (1 is already an integer). > > > If you really wanted to add this as Ruby code (rather than trying to > > leverage ActiveRecord directly, I'd suggest something at least a bit > > more idiomatic if no more efficient. > > > classPerson< ActiveRecord::Base > > belongs_to :household > > end > > > class Household < ActiveRecord::Base > > has_many :people > > > # reads all records, then aCOUNT(*) query to determine people > > def self.single_person_households > > find(:all).select {|household| household.people.count== 1 } > > end > > > # Or since the original question was for acount, > > # not the actual records... > > # Get just theCOUNTof singlepersonhouseholds > > def self.count_single_person_households > > connection.select_value(<<-ENDSQL) > > SELECTCOUNT(households.id) AS the_count > > FROM households > > INNER JOIN people ON people.household_id = household.id > > GROUP BY households.id > > HAVINGCOUNT(people.id) = 1 > > ENDSQL > > end > > end > > > puts Household.count_single_person_households > > Household.single_person_households.each do |household| > > puts household.name > > end > > > -Rob > > > > NOTE: If you create a view called single_person_household.html.erb, > > > then you will need a route that maps to that view in your routes.rb > > > file, such as > > > > map.connect 'single_person_household', :controller => > > > 'households', :action => 'single_person_household' > > > > In your view, you will use @households_with_one. > > > > By the way, before I post code, I test it, so I know that I am > > > actually answering the question which I understood to have been asked. > > > > Sandy > > > Rob Biedenharn > > [email protected] http://AgileConsultingLLC.com/ > > [email protected] http://GaslightSoftware.com/-Hide quoted text - > > > - Show quoted text - > > Rob, > > I agree that SQL is more efficient than the Ruby code. However, not > every application requires the ultimate in database 'efficiency', and > my experience is that such efficiency, at the expense of coding time > and clarity, is often overrated > > As far as the "original question" goes, he said, "I am assuming that > the output from this could be used to get the name field from > households." The fact that he wants the name field from the > households implies that he needs the array such that he can then > display the name field. Thecount, alone, doesn't supply the name > field. > > Sandy
Worked perfectly again Sandy. Thanks Bob -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

