按ActiveRecord中的特定ID排序

时间:2013-09-24 20:50:55

标签: ruby-on-rails ruby-on-rails-3 activerecord

我继承了另一个程序员的Rails3项目,而且我对rails总体来说相当新。他有一个看起来按特定id排序​​的查询。有人可以解释一下这在实际的SQL中是如何解决的吗?我认为这段代码正在杀死db并随后使用rails。我试图在记录器中输出它,但即使配置为:debug也似乎无法获得实际的SQL输出。在这里大量搜索(在SO上)并没有清楚地解释这个查询的外观。代码如下:

options = {
              select: "SUM(1) AS num_demos, product_id ",
              group:  "product_id",                
              order:  "num_demos ASC",
            }
  product_ids = Demo.where("state = 'waitlisted'").find(:all, options).collect{|d| d.product_id}
  sort_product_ids = product_ids.collect{|product_id| "id = #{product_id}"}   
  Product.where(visible: true, id: product_ids).order(sort_product_ids.join(', '))   

据我所知,最后一行将使用ORDER BY“id = 1,id = 3,...”等对产品表创建一个查询,这对于我。所有线索都很受欢迎。

3 个答案:

答案 0 :(得分:3)

要按给定的ID数组进行选择和排序,您可以使用此

Product.where(visible: true, id: product_ids)
.order( "field(id,#{product_ids.join(',')})" )

答案 1 :(得分:1)

快速分析正在发生的事情,因为它可以帮助您了解如何为替换查询做些什么。

options = {
              select: "SUM(1) AS num_demos, product_id ",
              group:  "product_id",                
              order:  "num_demos ASC",
            }
product_ids = Demo.where("state = 'waitlisted'").find(:all, options).collect{|d| d.product_id}

此行将生成

SELECT SUM(1) as num_demos, product_id FROM "demos" WHERE (state = 'waitlisted') GROUP BY product_id

并返回一个Demo个对象数组,按照组中count(*)个行排序,其中只加载了product_id属性,并且可供您使用。

接下来,

sort_product_ids = product_ids.collect{|product_id| "id = #{product_id}"}   

会生成映射到格式"id = x"的product_ids集合。 IE:如果上一个结果返回10个结果,product_ids范围为1..10,sort_product_ids现在等同于["id = 1", "id = 2", "id = 3", "id = 4", "id = 5", "id = 6", "id = 7", "id = 8", "id = 9", "id = 10"]

最后,

Product.where(visible: true, id: product_ids).order(sort_product_ids.join(', '))

选择列Productsvisible的所有true,其id位于product_ids数组中(正如我们之前发现的那样) ,实际上是一个Demo对象的数组,而不是整数 - 这可能导致查询失败)。然后,它要求SQL按sort_product_ids对结果列表进行排序(以字符串"id = 1, id = 2, ... id = 10"而不是数组["id = 1", "id = 2", ... "id = 10"]发送)。

更多信息,请访问: http://guides.rubyonrails.org/active_record_querying.html http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html

答案 2 :(得分:0)

如果你使用的是 PostgreSQL,可以考虑使用 WITH ORDINALITY,这是比其他方式最快的方式。见this thread

将此方法应用于 Ruby on Rails,例如:

class SpecifiedByIds
  def specified_by_ids(ids)
    joins(
      <<~SQL
        LEFT JOIN unnest(array[#{ids.join(',')}])
        WITH ORDINALITY AS t(id,odr) ON t.id = #{table_name}.id
      SQL
    ).order('t.odr')
  end
end

class MyModel < ActiveRecord::Base
  extend SpecifiedByIds
end