:group, , , , , , , , " />

Aliasing MySQL Functions with ActiveRecord

January 31, 2009

Changing column data to use MySQL functions instead of the actual column data for Ruby on Rails ActiveRecord is simple. To allow ActiveRecord to retrieve the data of the function,  alias it to the column name.

Event.find :all, :select => 'substring(name, 1, 10) as name'

This produces the follow SQL query using MySQL SUBSTRING function:

select substring(name, 1, 10) as name from events; 

ActiveRecord will pull the truncated name (the first 10 characters) in the function data into the ActiveRecord field name. This can be very useful for offloading some work to MySQL by using its operations rather than performing the same functions in memory with Rails code.

Aliasing methods can be useful when combined with the GROUP BY functionality. For example, the following query will count the number of events that start on the same day.

events = Event.find :all, :select => 'DATE(start_time) as start_time, count(*) as num_events', :group => 'DATE(start_time)'

Notes and Caveats

Be aware that several issues exist when using MySQL aliasing with ActiveRecord.

Eager Loading

One note is is that ActiveRecord doesn’t support :select with eager loading. This means that the :select clause is ignored when :include is specified. To work around this problem (and get a performance benefit by selecting fewer columns), install one of the many eager loading plugins referenced on this ticket. Perhaps there are better ones, but I wrote eload select and have stuck to it.

script/plugin install http://arperftoolkit.rubyforge.org/svn/trunk/eload_select

Aliased Column vs. MySQL Function

Another caveat is that due to a MySQL “Not a Bug”, the full function DATE(start_time) must be specified instead of just the alias start_time.  This might seem obvious, but the  ORDER BY worked the same way. However, ORDER BY clause does the opposite and uses the function aliased to name instead of the column name. For example,here the data is sorted on the second letter of the title (the substring function).

Event.find :all, :select => 'substring(title, 2) as title',  :o rder =>'title'

which produces this SQL query:

select substring(title, 2) as title from events order by title;

Leave a Reply