首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django ORM在具有相同值的字段上进行左连接

Django ORM在具有相同值的字段上进行左连接
EN

Stack Overflow用户
提问于 2019-03-13 14:18:31
回答 1查看 225关注 0票数 0

我正在为水文学家写网页界面。水文学家应该看到不同水文测量值的表格,如下所示。

代码语言:javascript
运行
复制
+----------------+----------------------+-------+--------------------+-------------+------------------+
| observation_id | observation_datetime | level | water_temperature  |precipitation|precipitation_type|
+----------------+----------------------+-------+--------------------+-------------+------------------+

| 1 | 2019-03-11 11:00:00 | 11 | 21 | 31 |
| 2 | 2019-03-12 12:00:00 | 12 | 22 | 32 |
| 3 | 2019-03-13 13:00:00 | 13 | 23 | 33 |
| 4 | 2019-03-14 14:00:00 | 14 | 24 | 34 |

我有这些描述度量的模型。

代码语言:javascript
运行
复制
class AbstractMeasurement(model.Model):
    observation_datetime = models.DateTimeField()
    observation = models.ForeignKey(Observation, on_delete = models.DO_NOTHING)

class Meta:
    abstract = True

class Level(AbstractMeasurement):
    level = models.DecimalField()

class WaterTemperature(AbstractMeasurement):
    air_temperature = models.DecimalField()

class Precipitation(AbstractMeasurement):
    precipitation = models.DecimalField()
    precipitation_type = models.CharField()

等。

level主要的测量和测量离不开Level。Level是基本模型。

在mysql中,我可以通过下面的查询来完成

代码语言:javascript
运行
复制
    SELECT level.observation_id, 
            level.observation_datetime, 
            level.level, 
            water_temperature.water_temperature, 
            precipitation.precipitation, 
            precipitation.precipitation_type 
    FROM level 
    LEFT JOIN precipitation ON 
            level.observation_datetime = precipitation.observation_datetime 
            AND 
            level.observation_id = precipitation.observation_id 
    LEFT JOIN water_temperature ON 
            level.observation_datetime = water_temperature.observation_datetime 
            AND 
            level.observation_id = water_temperature.observation_id;

如何在没有外键关系的模型中加入django?

EN

回答 1

Stack Overflow用户

发布于 2019-03-13 16:01:18

您可以实现您想要的结果,但这将是不必要的低效(甚至比您发布的SQL查询还要低)。由于您当前的模型结构已经相当扭曲,如果您可以更改模型,那么您应该这样做。

也就是说,下面是如何将Precipitation数据带入Level查询的方法。每个字段和行都需要一个子查询:

代码语言:javascript
运行
复制
from django.db.models import Q, OuterRef, Subquery

join_criteria = Q(
    observation_id=OuterRef('observation_id'), 
    observation_datetime = OuterRef('observation_datetime')
)

subquery_precipitation = Subquery(Precipitation.objects
    .filter(join_criteria)
    .values('precipitation')[:1])

subquery_precipitation_type = Subquery(Precipitation.objects
    .filter(join_criteria)
    .values('precipitation_type')[:1])

levels = (Level.objects
        .annotate(precipitation=subquery_precipitation)
        .annotate(precipitation_type=subquery_precipitation_type))

现在,尝试将字段数乘以查询中的预期行数-这就是需要执行的子查询数。

因此,这是一个概念证明,您可以在小表和几个字段中使用。它不适合于大型数据集和许多字段。你真的应该重新考虑一下你的模型。

有了合适的模型,就可以很容易地实现你需要的东西。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55135563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档