从没有外键的两个模型的 JOIN 中检索值(Django)

Posted

技术标签:

【中文标题】从没有外键的两个模型的 JOIN 中检索值(Django)【英文标题】:Retrieve values from the JOIN of two models without foreign key (Django) 【发布时间】:2021-01-07 11:10:46 【问题描述】:

我想检索与两个不同模型相关的两列的值(没有外键)。在 SQL 中,我会这样写:

SELECT employees.name, companies.name
FROM employees
JOIN companies
ON companies.location=employees.location;

假设这两个模型分别称为EmployeeCompany。它们没有共同的外键,我不能更改模型。

我怎样才能在 Django 中拥有相同的功能?我是否必须编写原始 SQL 查询?

【问题讨论】:

你能过滤位置吗? location 只是一个常规列,在我的情况下它不是 Django 模型。 你看过这个吗?***.com/questions/39291372/… @BriseBalloches 谢谢,我能够使用您链接的答案中的信息来制定解决方案。 【参考方案1】:

我将添加答案作为其他用户的参考,因为在 cmets 中链接的类似问题不是很详细。

from django.db.models import Subquery, OuterRef

Employee.objects.annotate(
    company_name=Subquery(
        Company.objects.filter(location=OuterRef('location')).values('name')
    )
).values_list('name', 'company_name')

说明

把它分成几部分(从里到外):

1.

OuterRef('location')

这会创建对Employee 对象的location 属性的引用。之所以称为 OuterRef,是因为它指的是在子查询(即调用子查询)之外使用的模型。

2.

Subquery(Company.objects.filter(location=OuterRef('location')).values('name'))

子查询返回location与员工相同的所有公司的名称。

3.

Employee.objects.annotate(
    company_name=Subquery(...)
)

这基本上是用一个名为company_name 的新字段来注释“全局”查询返回的Employee 对象。此字段存储来自 (2) 的子查询的结果。

生成的 SQL 查询将如下所示:

SELECT employees.name,
  (SELECT companies.name
   FROM companies
   WHERE companies.location = employees.location) AS company_name
FROM employees

(我简化了一些由 Django ORM 产生的混乱)。

注意

请务必注意,这将使用 子查询(而不是 joins)。在某些情况下,这可能会影响性能。

【讨论】:

【参考方案2】:

对于此类请求,您应该编写原始 SQL...

但是您确定这里实际上不需要外键吗?

【讨论】:

我无法更改模型,因此在我的情况下不能选择外键。另外,我想将我的问题集中在我当前设置中实现与我发布的 SQL 查询相同的结果的可能性(或不)上。如果 Django 在没有原始 SQL 查询的情况下无法做到这一点,我想这就是答案 :)

以上是关于从没有外键的两个模型的 JOIN 中检索值(Django)的主要内容,如果未能解决你的问题,请参考以下文章

SQL怎么在有外键的主键表中插数据

如何删除有外键的mysql记录

如何在DJANGO里,向有外键的DB里插入数据

django模型在具有外键的字段中没有列错误

知识盲点:存在外键的的表,在插入数据时应该如何操作?

如何插入表有外键?