Rails选择子查询(如果可能的话,没有finder_sql)

时间:2014-02-04 15:39:28

标签: mysql sql ruby-on-rails activerecord subquery

我有一个名为Object的模型(并不重要)

它有一个默认价格(列称为“价格”)。

然后有一个Schedule对象允许覆盖特定日期的价格。

我希望能够在SQL查询期间确定MINIMUM价格(根据定义,默认值和“当前”价格之间的MINIMUM),以便能够按计算的最低价格进行ORDER BY

我想让我的搜索查询尽可能高效,我想知道我是否可以 做那样的事情:

Object.select("id AS p_id, id, (SELECT MIN(`schedules`.`price`) FROM `schedules` WHERE `schedules`.`object_id` = p_id`) AS objects.min_price").limit(5)

但是,它会生成一个奇怪的SQL,如下所示:

SELECT `objects`.`id` AS t0_r0, `objects`.`title` AS t0_r1, `objects`.`created_at` AS t0_r2, `objects`.`updated_at` AS t0_r3, `objects`.`preferences` AS t0_r4 ........ (a lot of columns here) ... ` WHERE `objects`.`id` IN (1, 2, 3, 4 ....)

所以,你可以看到它不起作用。首先 - 它从对象表中加载所有列,其次 - 它看起来很糟糕。

我不想使用finder_sql的原因是我有很多可选参数和东西,所以在获取结果本身之前使用AR :: Relation对象是非常优选的。

除了上面提到的,我在DB中有很多记录,我认为将它们全部加载到内存中并不是一个好主意,这也是我想要执行这个子查询的主要原因 - 只是为了过滤 - 尽可能多的记录。

有人可以帮助我更有效地做到这一点吗?

1 个答案:

答案 0 :(得分:16)

如果单独生成子查询并使用连接而不是相关子查询,则可以使这更容易:

subquery = Schedule.select('MIN(price) as min_price, object_id').group(:object_id).to_sql
Object.joins("JOIN (#{subquery}) schedules ON objects.p_id = schedules.object_id").
       select('objects.*, schedules.min_price').limit(5)