When is it appropriate to resort to find_by_sql?
I’m all for portable, easily maintained code. I’m a HUGE fan the new
ActiveRecord::Relation model in Rails 3.0 I keenly feel the peril of
dropping into find_by_sql().
Question 1: is there’s a snowball’s chance in Hades for the following
code to be written WITHOUT resorting find_by_sql()?
inner_query =<<EOQ
SELECT DATE(st.datetime) AS start_time,
DATE(et.datetime - INTERVAL 1 DAY) AS end_time,
DATEDIFF(et.datetime, st.datetime) AS day_count,
sbs.quantity AS quantity,
sbs.cost AS cost
FROM service_bills as sbs
INNER JOIN time_dimensions AS st ON st.id = sbs.start_time_id
INNER JOIN time_dimensions AS et ON et.id = sbs.end_time_id
WHERE sbs.metered_service_id IN (#{metered_service_ids})
EOQ
I’m sure it’s possible using a ServiceBill.find() construct where each
clause is essentially a quoted string from the above, but by that point,
I’d be hard pressed to say that is clearer or more maintainable.
Question 2: Nested queries. In my system, inner_query is, in fact, an
inner query that appears within this little monster:
outer_query =<<EOQ
SELECT st.id AS start_time_id,
et.id AS end_time_id,
DATE(st.datetime) AS time,
SUM(bills.quantity/bills.day_count) AS daily_quantity,
SUM(bills.cost/bills.day_count) AS daily_cost
FROM time_dimensions AS st
INNER JOIN time_dimensions AS et ON DATE(st.datetime + INTERVAL 1 DAY)
= DATE(et.datetime)
INNER JOIN (#{inner_query}) AS bills
WHERE st.datetime BETWEEN bills.start_time AND bills.end_time
AND st.is_midnight = 1
GROUP BY st.id
EOQ
Even if both of these queries could be cast into a find() construct, I
don’t see how to create the equivalent of nested queries: it seems like
I’d have to “pop back up” to the Rails level, which is problematic for
really large datasets.
So: If ActiveRecord::Relation.find() really cannot handle queries of
this complexity, I’m okay with that. But if it can, I’d welcome
pointers or documentation on how to code them.
TIA.
- ff