4

我继承了另一个程序员的 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, ..." 等创建针对产品表的查询,这对我来说没有多大意义。所有线索表示赞赏。

4

3 回答 3

3

快速细分正在发生的事情,因为它将帮助您了解如何处理您的替换查询。

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}"}   

生成映射到格式的 product_ids 集合"id = x"。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(', '))

选择Products列在的所有位置visibletrue并且它们id在数组中product_ids(正如我们之前发现的,它实际上是一个Demo对象数组,而不是整数 - 这可能会导致查询失败)。sort_product_ids然后,它要求 SQL 按(作为字符串"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

于 2013-09-24T21:20:11.707 回答
3

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

Product.where(visible: true, id: product_ids)
.order( "field(id,#{product_ids.join(',')})" )
于 2013-09-24T21:02:46.937 回答
0

如果您使用的是 PostgreSQL,请考虑使用WITH ORDINALITY,它是与其他方式相比最快的方式。看到这个线程

将此方法应用于 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
于 2021-04-17T16:42:13.633 回答