Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在过滤查询集上使用Django窗口函数_Django_Django Queryset - Fatal编程技术网

在过滤查询集上使用Django窗口函数

在过滤查询集上使用Django窗口函数,django,django-queryset,Django,Django Queryset,在过滤查询集上使用窗口函数时,我遇到了一个令人惊讶的难题 考虑两个模型:mymodel和relatedmodel,其中存在一对多关系(即relatedmodel在mymodel中有一个外键) 我用的是这样的东西: window_lag = Window(expression=Lag("pk"), order_by=order_by) window_lead = Window(expression=Lead("pk"), order_by=order_by)

在过滤查询集上使用窗口函数时,我遇到了一个令人惊讶的难题

考虑两个模型:mymodel和relatedmodel,其中存在一对多关系(即relatedmodel在mymodel中有一个外键)

我用的是这样的东西:

window_lag = Window(expression=Lag("pk"), order_by=order_by)
window_lead = Window(expression=Lead("pk"), order_by=order_by)
window_rownnum = Window(expression=RowNumber(), order_by=order_by)
qs1 = mymodel.objects.filter(relatedmodel__field=XXX)
qs2 = qs1.annotate(row=window_rownnum, prior=window_lag, next=window_lead)
qs3 = qs2.filter(pk=myid)
这将为对象pk=myid返回一个可爱的结果。我现在知道了它在过滤列表中的位置,以及它的上一个和下一个位置,我在浏览过滤列表时使用它会产生很大的效果

值得注意的是,len(qs1)=len(qs2)是列表的大小,len(qs3)=1

唉,我刚刚发现,当过滤器不太具体时,这种情况会严重破坏:

window_lag = Window(expression=Lag("pk"), order_by=order_by)
window_lead = Window(expression=Lead("pk"), order_by=order_by)
window_rownnum = Window(expression=RowNumber(), order_by=order_by)
qs1 = mymodel.objects.filter(relatedmodel__field__contains=X)
qs2 = qs1.annotate(row=window_rownnum, prior=window_lag, next=window_lead)
qs3 = qs2.filter(pk=myid)
在这个例子中,qs2突然比qs1有更多的行!len(qs2)>len(qs1)

这在某种意义上完全破坏了浏览器(因为Previor和next不再可靠)。多余的行是重复的mymodel对象,只要有多个relatedmodel对象与条件匹配

我已经跟踪到生成的SQL

这是qs1的SQL的形式:

SELECT DISTINCT 
  "mymodel"."id", "mymodel"."order_by" ....
FROM "mymodel"
INNER JOIN "relatedmodel" ON ("mymodel"."id" = "relatedmodel"."mymodel_id")
WHERE ("related_model"."field"::text LIKE '%X%')
ORDER BY "mymodel"."order_by" ASC
这在我的数据库引擎中作为SQL查询运行良好,并返回与Django看到的行数相同的行数。一切都好

那么qs2生成的SQL类似于:

SELECT DISTINCT 
  ROW_NUMBER() OVER (ORDER BY "mymodel"."order_by" ASC) AS "row",
  LAG("mymodel"."id", 1) OVER (ORDER BY "mymodel"."order_by" ASC) AS "prior,
  LEAD("mymodel"."id", 1) OVER (ORDER BY "mymodel"."order_by" ASC) AS "next",
  "mymodel"."id", "mymodel"."order_by" ....
FROM "mymodel"
INNER JOIN "relatedmodel" ON ("mymodel"."id" = "relatedmodel"."mymodel_id")
WHERE ("related_model"."field"::text LIKE '%X%')
ORDER BY "mymodel"."order_by" ASC
同样,这会产生与我在Django中看到的相同数量的行,但当relatedmodel匹配多次时,这比qs1多

我可以修改SQL并得到我想要的,即通过过滤后的窗口:

SELECT 
  ROW_NUMBER() OVER (ORDER BY "mymodel"."order_by" ASC) AS "row"
  LAG("mymodel"."id", 1) OVER (ORDER BY "mymodel"."order_by" ASC) AS "prior,
  LEAD("mymodel"."id", 1) OVER (ORDER BY "mymodel"."order_by" ASC) AS "next",
  "id", "order_by" ....
FROM (
  SELECT DISTINCT 
    "mymodel"."id", "mymodel"."order_by" ....
  FROM "mymodel"
  INNER JOIN "relatedmodel" ON ("mymodel"."id" = "relatedmodel"."mymodel_id")
  WHERE ("related_model"."field"::text LIKE '%X%')
  ORDER BY "mymodel"."order_by" ASC
) AS QS
它工作得很好,返回的行数与qs1相同

在SELECT中只添加一个窗口函数会导致DISTINCT由于某种原因而失败。DISTINCT在没有窗口函数(只返回唯一的mymodel行)的情况下可以正常工作,但添加窗口函数会破坏这一点

将筛选器用作窗口函数上的子查询是有效的

Django支持子查询,但我在这里找不到应用它们的方法


所以我想知道是否有办法做到这一点。也就是说,将注释作为QuerySet的包装而不是QuerySet中的附加列来应用。

试着换一种方式来考虑它。把window函数放在子查询中,把filter子句放在外部查询中,看看它能做些什么。我设想会有一个问题。正如所期望的结果一样,要获得一个过滤查询集(最终用户应用的过滤器),然后针对该对象列表,用该列表上的行号(在列表中)和上一个和下一个对象的主键注释每一行,以帮助导航(过滤的)列表。如果我在筛选之前应用窗口函数,那么结果列表中有来自未筛选列表的行号、优先级和NEXT。还是我误会了?我想你是对的。很抱歉我在这件事上毫无帮助。