我继承了另一个程序员的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,...”等对产品表创建一个查询,这对于我。所有线索都很受欢迎。
答案 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(', '))
选择列Products
为visible
的所有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