提问人:hardik 提问时间:11/13/2023 最后编辑:hardik 更新时间:11/14/2023 访问量:87
“where”覆盖了我在 rails 中的默认“order”
'where' is overriding my default 'order' in rails
问:
我正在尝试根据结果制作一个 qyery,我正在为某些任务应用另一个查询。
在这里,我有一种filter_based_on_ticket_creation方法,其中我根据降序获取一些数据,这是我的过滤器之一,基于该数据,我正在进行另一个查询,这将提供一些我想要显示的其他详细信息。
这是最狡猾的,
def fetch_deallocations_based_on_department
department = params[:department]
deallocations = []
filter_based_on_ticket_creation(params).joins(:resource_info).where('resource_infos.department_name = ?',department).order(due_date: :asc).limit(5).each do |details|
deallocations.push([details.developer.name,details.due_date.present? ? details.due_date&.strftime('%d / %m / %Y') : 'Date not assigned'])
end
render json: deallocations
end
def filter_based_on_ticket_creation(params)
if (params[:q].present? && params[:q][:updated_at_lteq].present?)
@q.result.order(updated_at: :desc).limit(params[:q][:updated_at_lteq].to_i)
else
@q.result
end
end
在这里我总共有 32 条撤派记录,
irb(main):002:0> Deallocation.all.pluck(:id)
Deallocation Pluck (0.5ms) SELECT "deallocations"."id" FROM "deallocations"
=> [75, 24, 25, 26, 82, 27, 28, 74, 36, 41, 78, 58, 76, 53, 29, 40, 81, 30, 77, 23, 38, 39, 54, 68, 57, 70, 71, 72, 79, 73, 80, 83]
所以现在我想做一个过滤器,给出最新的 5 或 10 张票,为此我做了一种方法(filter_based_on_ticket_creation(params))给我最新的数据,基于updated_at意味着它给出最新的 5 条记录或 10 条记录 这里filter_based_on_ticket_creation(params)返回一些数据
Deallocation Load (0.4ms) SELECT "deallocations".* FROM "deallocations" ORDER BY "deallocations"."updated_at" DESC LIMIT $1
pry(#<DeallocationsController>)> @filterd_deallocation.pluck(:id)
=> [75, 83, 82, 81, 40]
因此,在应用此过滤器后,我有 2 个用例,一个是我想显示这 5 条记录,另一个用例是我在过滤后的数据上应用一些 where 和 join 条件。
当我在我的 fetch_deallocations_based_on_department 方法上应用 where 条件时,它将覆盖查询并给出不同的输出
@filterd_deallocation.joins(:resource_info).where('resource_infos.department_name = ?','ROR')
Deallocation Load (0.6ms) SELECT "deallocations".* FROM "deallocations" INNER JOIN "cims"."resource_infos" ON "cims"."resource_infos"."id" = "deallocations"."resource_info_id" WHERE (resource_infos.department_name = 'ROR') ORDER BY "deallocations"."updated_at" DESC LIMIT $1 [["LIMIT", 5]]
@filterd_deallocation.joins(:resource_info).where('resource_infos.department_name = ?','ROR').pluck(:id)
Deallocation Pluck (1.3ms) SELECT "deallocations"."id" FROM "deallocations" INNER JOIN "cims"."resource_infos" ON "cims"."resource_infos"."id" = "deallocations"."resource_info_id" WHERE (resource_infos.department_name = 'ROR') ORDER BY "deallocations"."updated_at" DESC LIMIT $1 [["LIMIT", 5]]
↳ (pry):4:in `deallocation_dashboard'
=> [75, 83, 40, 29, 53] # here additional 40,29,53 ids are coming
所以在这里你可以看到 在 SQL 中,filter_based_on_ticket_params方法进行此查询
ELECT "deallocations".* FROM "deallocations" ORDER BY "deallocations"."updated_at" DESC LIMIT $1
所以当我应用这个查询时
filter_based_on_ticket_creation(params).joins(:resource_info).where('resource_infos.department_name = ?',department).order(due_date: :asc).limit(5)
它将覆盖默认查询,因为 SQL 查询的执行顺序,其中“where”的优先级高于“order”,因此它将首先进行“where”查询,并基于该数据进行“order”
SELECT "deallocations".* FROM "deallocations" INNER JOIN "cims"."resource_infos" ON "cims"."resource_infos"."id" = "deallocations"."resource_info_id" WHERE (resource_infos.department_name = 'ROR') ORDER BY "deallocations"."updated_at" DESC LIMIT $1
所以我想要一个持久查询,我该怎么办意味着第二个查询不会改变SQL流的执行,我只根据我的第一个查询数据得到结果。
答:
额外的 2 个 ID 即将到来,因为您告诉数据库您想要 5 个结果。
在上一个查询中,有 5 个结果。在你应用过滤器后,其中只有 3 个(75、83、40)与此匹配,但你仍然告诉数据库你想要 5 个结果 (),因此数据库会继续查找并找到更多最初未包含在 5 个中的记录。.limit(5)
如果没有关于用例的更多上下文(为什么一开始正好是 5 个结果,然后更少?),很难说你应该如何解决这个问题。
但限制可能不是正确的工具。
评论
我不能给你一个完整的答案,因为我对 ruby on rails 一无所知,但这应该有助于你前进。
据我了解您的问题: 您有最新的 deallocation-ids [Query1] 的结果,并希望根据相关部门值筛选这些结果。[查询 2]
您不希望出现新结果,该结果显示部门的所有最新解除分配 ID。
最简单的方法是从 query1 提供所需的 ID。
# No idea if this is the way to write this in ruby
Deallocation.joins(:resource_info).where(deallaction.id: filterd_deallocation).where('resource_infos.department_name = ?',department)
这应该会导致类似
SELECT "deallocations".*
FROM "deallocations"
INNER JOIN "cims"."resource_infos" ON "cims"."resource_infos"."id" = "deallocations"."resource_info_id"
WHERE
(resource_infos.department_name = 'ROR')
AND
(deallocations.id IN (75,83))
正如您已经注意到的那样,sql 执行有严格的顺序,并且它按预期工作。 顺序仅适用于已按位置筛选的结果集。 我敦促您重新考虑如何获取和过滤数据的方法。
评论