Jon Bauman
2006-Apr-11 06:02 UTC
[Rails] Getting distinct years from a date column the Rails way
I have an original_at column in my photos table. I''d like to get a list of distinct years that occur in this column, and some of the values are NULL. I see two ways of doing this. The SQLish way: photos = Photo.find :all, :select => ''distinct year(original_at)'' This is efficient in that it utilizes the database to do the filtering, and the code is not too ugly. The big downside is that I have to access the results like this: @years = photos.map {|p| p[''year(original_at)''] } Then, there''s the ActiveRecord way (as best I can figure it): @years = Photo.find(:all).map {|p| p.original_at && p.original_at.year }.uniq This gives a nice array of the years, but it''s sorta ugly, and it''s using model code for things the database is good at (filtering results). Can anyone suggest a better or more idiomatic approach to this? It seems there should be support for finders of a certain column that return an array of objects of the column''s type rather than the model type. Something like: @years = Photo.find_column, :select => ''distinct year(original_at)'' Does that seem useful, or is there a way to do that cleanly now? -- Posted via http://www.ruby-forum.com/.
joey__
2006-Apr-11 07:16 UTC
[Rails] Re: Getting distinct years from a date column the Rails way
Jon Bauman wrote:> I have an original_at column in my photos table. I''d like to get a list > of distinct years that occur in this column, and some of the values are > NULL. I see two ways of doing this. The SQLish way: > > photos = Photo.find :all, :select => ''distinct year(original_at)'' > > This is efficient in that it utilizes the database to do the filtering, > and the code is not too ugly. The big downside is that I have to access > the results like this: > > @years = photos.map {|p| p[''year(original_at)''] } > > Then, there''s the ActiveRecord way (as best I can figure it): > > @years = Photo.find(:all).map {|p| p.original_at && p.original_at.year > }.uniq > > This gives a nice array of the years, but it''s sorta ugly, and it''s > using model code for things the database is good at (filtering results). > > Can anyone suggest a better or more idiomatic approach to this? It seems > there should be support for finders of a certain column that return an > array of objects of the column''s type rather than the model type. > Something like: > > @years = Photo.find_column, :select => ''distinct year(original_at)'' > > Does that seem useful, or is there a way to do that cleanly now?Maybe: photos = Photo.find :all, :select => ''distinct year(original_at) as orginial_year'' I''m no SQL wizard! j`ey -- Posted via http://www.ruby-forum.com/.
Jon Bauman
2006-Apr-11 11:46 UTC
[Rails] Re: Getting distinct years from a date column the Rails way
Thanks. Now I have this, which is the best to far: @years = Photo.find(:all, :select => ''distinct year(original_at) as year'').map(&:year) This is better than my earlier attempts, but I still think it would be nice if there were a way to do finds that returned an array of attribute/column-specific objects as opposed to ActiveRecord objects. If one were dealing wit a very large result (say, distinct fist names in a huge list of users) the overhead of the map call might be annoying. Plus, the results that one gets from the actual find method (for example): [#<Photo:0x23387ec @attributes={"year"=>"2003"}>, #<Photo:0x23386fc @attributes={"year"=>"2002"}>, #<Photo:0x23385e4 @attributes={"year"=>nil}>] Don''t really make sense. These shouldn''t be Photo objects, since they don''t really represent photos. We already have ActiveRecord::Base.count_by_sql, so why not something for this? Thanks again for the suggestion. Your SQL magic is greater than mine. joey__ wrote:> Jon Bauman wrote: >> I have an original_at column in my photos table. I''d like to get a list >> of distinct years that occur in this column, and some of the values are >> NULL. I see two ways of doing this. The SQLish way: >> >> photos = Photo.find :all, :select => ''distinct year(original_at)'' >> >> This is efficient in that it utilizes the database to do the filtering, >> and the code is not too ugly. The big downside is that I have to access >> the results like this: >> >> @years = photos.map {|p| p[''year(original_at)''] } >> >> Then, there''s the ActiveRecord way (as best I can figure it): >> >> @years = Photo.find(:all).map {|p| p.original_at && p.original_at.year >> }.uniq >> >> This gives a nice array of the years, but it''s sorta ugly, and it''s >> using model code for things the database is good at (filtering results). >> >> Can anyone suggest a better or more idiomatic approach to this? It seems >> there should be support for finders of a certain column that return an >> array of objects of the column''s type rather than the model type. >> Something like: >> >> @years = Photo.find_column, :select => ''distinct year(original_at)'' >> >> Does that seem useful, or is there a way to do that cleanly now? > > Maybe: > photos = Photo.find :all, :select => ''distinct year(original_at) as > orginial_year'' > I''m no SQL wizard! > j`ey-- Posted via http://www.ruby-forum.com/.