我正在为水文学家编写网络界面。水文学家应该看到这样的不同水文测量表。
+----------------+----------------------+-------+--------------------+-------------+------------------+
| 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 |
我有这些模型来描述测量
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()
等等
水平主要测量和测量不能没有水平。等级是基本模型。
在mysql中,我可以通过此查询来完成
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中左键加入?
你可以实现你想要的,但它会不必要地低效(甚至比你发布的SQL查询更多)。由于您当前的模型结构相当扭曲,如果您可以更改模型,则应该。
也就是说,这是如何带来例如Precipitation
数据到你的Level
查询。每个字段和行需要一个子查询:
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))
现在尝试将字段数乘以查询中的预期行数 - 这是需要执行的子查询数。
因此,这是一个概念证明,您可以在小桌子和几个字段中使用。它不适用于大型数据集和许多领域。你应该重新考虑你的模型。
有了合适的型号,它应该很容易实现您的需求。