我不是Rails的新手,但到目前为止我还没有做过这么复杂的事情,所以我很好奇经验丰富的rails开发人员可能分享的内容:
我有一个sql查询,它将4个左右的表连接到一个输出中:
SELECT places.id, places.name, places.email, places.website, places.blurb, external_ratings.rating, photos.data_file_name
FROM `scannables`
INNER JOIN places ON scannables.place_id = places.id
INNER JOIN locations ON places.location_id = locations.id
LEFT JOIN external_ratings ON scannables.place_id = external_ratings.place_id
LEFT JOIN photos ON scannables.place_id = photos.place_id
WHERE locations.id = 2474 AND scannables.bookdate BETWEEN '2009-08-29' and date_add('2009-08-29', INTERVAL 4 DAY)
GROUP BY scannables.place_id
HAVING SUM(scannables.available) >= 4
ORDER BY SUM(scannables.available) DESC, external_ratings.rating DESC
我在各种模型中定义了所有表关系,并且最初只使用这些定义的关系(使用活动记录)来提取各种数据,并且它工作正常,除了主要查询是最大的是非常慢,执行多个人查询。我的问题是,我应该在这个案例中转储Active Record并使用find_by_sql ......还是我错过了什么?
什么是Rails方式?
由于
答案 0 :(得分:11)
务实而不是担心维持“Rails纯度”更为重要。我喜欢命名的范围,关联以及与之相关的所有魔法。当然,我更喜欢那些运行原始SQL查询。但是,如果一个复杂的查询调用了find_by_sql,那么我将使用它而不会失去任何睡眠。
如果你需要支持多个数据库,那么你可能想把它变成纯粹的Rails方法,但这个要求很少见。
答案 1 :(得分:4)
其实我不喜欢那些答案所以我做了一点挖掘并且很幸运......
我更喜欢这个......
Place.find(:all,
:joins => "INNER JOIN scannables ON scannables.place_id = places.id",
:conditions => [ "places.location_id = ? and scannables.bookdate BETWEEN ? and ?", 2474, '2009-08-29', '2009-09-02' ],
:group => 'scannables.place_id',
:having => 'SUM(scannables.available) >= 4')
它更简单,我仍然可以使用所有漂亮的导轨机械来获得我不需要明确的部件..即少了两个连接!
虽然......我想知道是否有办法更简化它?这个关系在scannables和places之间定义...即has_many,属于......那么为什么我还需要指定INNER JOIN ON?不应该
:joins => :scannable work?
无论如何..它不喜欢那样......
答案 2 :(得分:2)
使用
:joins => :scannables
假设您已经设置了Place#has_many:scannables关联,应该可以工作(注意复数)。 #find的:join子选项接受字符串和命名关联。
答案 3 :(得分:0)
如果您有多个此类查询,可能需要考虑使用sequel。否则,我同意jdl。