如何在 django ORM 的 From 子句中编写子查询

Posted

技术标签:

【中文标题】如何在 django ORM 的 From 子句中编写子查询【英文标题】:How to write subquery in From clause in django ORM 【发布时间】:2020-07-06 21:56:07 【问题描述】:

我想用 django orm 编写这个查询

SELECT depname, empno, salary, enroll_date
FROM
  (SELECT depname, empno, salary, enroll_date,
          rank() OVER (PARTITION BY depname ORDER BY salary DESC) AS pos
     FROM empsalary
  ) AS ss
WHERE pos < 3;

我当前的 ORm 查询

EmpSalary.objects.values('depname', 'empno', 'salary', 'enroll_date').annotate(
pos= Window(
                expression=RowNumber(),
                partition_by=[F('depname')],
                order_by=F('salary').desc(),
            )
)

上面的ORM查询集大致翻译为内部查询

SELECT depname, empno, salary, enroll_date,
          rank() OVER (PARTITION BY depname ORDER BY salary DESC) AS pos
     FROM empsalary

我想知道如何在外部查询的 FROM 子句中获取整个内部查询。

【问题讨论】:

不用加.filter(pos__lt=3)吗? 它不起作用...给出一个异常窗口表达式不可过滤。 请查看pypi.org/project/django-sub-query 你找到不包含第三方包的解决方案了吗? 【参考方案1】:

确实,不可能在WHERE 子句中使用Window 查询。所以改为使用Subquery:

from django.db.models import OuterRef, Subquery

top_salaries = EmpSalary.objects.filter(
    depname=OuterRef('depname')
).order_by('-salary')[:3]
result = EmpSalary.objects.filter(
    pk__in=Subquery(top_salaries.values('pk'))
).values('depname', 'empno', 'salary', 'enroll_date')

【讨论】:

它不起作用。子查询放在外部查询的 WHERE 子句中。有没有办法让 SUBQUERY 进入 FROM 子句?

以上是关于如何在 django ORM 的 From 子句中编写子查询的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM:带后续过滤的窗口函数

Django 使用 ORM 和条件 Where 子句连接表

Django ORM:带有后续过滤的窗口函数

ON 子句 Laravel ORM 中的子查询

Django ORM - 具有不同选择子句的分组聚合

Django ORM 是不是在 sql where 子句中将已删除的字段映射到其他字段之前?