“where”覆盖了我在 rails 中的默认“order”

'where' is overriding my default 'order' in rails

提问人:hardik 提问时间:11/13/2023 最后编辑:hardik 更新时间:11/14/2023 访问量:87

问:

我正在尝试根据结果制作一个 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流的执行,我只根据我的第一个查询数据得到结果。

SQL Ruby-on-Rails Ruby PostgreSQL

评论

0赞 A.Copter 11/13/2023
您能否添加表格示例和(匿名)数据示例?仅从您的问题来看,似乎很难理解为什么第二个查询的 40,29,53 是不需要的结果。部门“ror”的最后一次解除分配是给定的结果可能是正确的。
0赞 hardik 11/14/2023
嗨@A.Copter我添加了更多描述,你现在可以检查了吗

答:

0赞 Siim Liiser 11/13/2023 #1

额外的 2 个 ID 即将到来,因为您告诉数据库您想要 5 个结果。

在上一个查询中,有 5 个结果。在你应用过滤器后,其中只有 3 个(75、83、40)与此匹配,但你仍然告诉数据库你想要 5 个结果 (),因此数据库会继续查找并找到更多最初未包含在 5 个中的记录。.limit(5)

如果没有关于用例的更多上下文(为什么一开始正好是 5 个结果,然后更少?),很难说你应该如何解决这个问题。

但限制可能不是正确的工具。

评论

0赞 hardik 11/14/2023
嗨,斯利姆,我添加了更多上下文,您现在可以检查一下。
0赞 A.Copter 11/14/2023 #2

我不能给你一个完整的答案,因为我对 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 执行有严格的顺序,并且它按预期工作。 顺序仅适用于已按位置筛选的结果集。 我敦促您重新考虑如何获取和过滤数据的方法。