我正在做一些原型(prototype)设计,并有一个像这样的简单模型
class SampleModel(models.Model):
user_id = models.IntegerField(default=0, db_index=True)
staff_id = models.IntegerField(default=0, db_index=True)
timestamp = models.DateTimeField(default=timezone.now, db_index=True)
objects = AsOfManager()
现在我们需要执行需要自连接的查询,用原始 SQL 编写的查询就像这样:
SELECT X.* FROM no_chain_samplemodel as X
JOIN (SELECT user_id, MAX(timestamp) AS timestamp
FROM no_chain_samplemodel
GROUP BY user_id) AS Y
ON (X.user_id = Y.user_id and X.timestamp = Y.timestamp);
此查询应为每个 user_id 返回按时间戳排序的最后一行。每个“链”(与 user_id 相关的行)都可能有数千行。
现在我可以使用原始 SQL,但随后我失去了可组合性,我想返回另一个查询集。 同时,如果能够更轻松地编写原始 SQL 就好了,所以我想我可以使用数据库 View 。
View 可能是这样的
CREATE VIEW no_chain_sample_model_with_max_date AS SELECT user_id AS id, MAX(timestamp) AS timestamp
FROM no_chain_samplemodel
GROUP BY user_id;
因此引用 View 的模型可以简单地像这样:
class SampleModelWithMaxDate(models.Model):
class Meta:
managed = False
db_table = 'no_chain_sample_model_with_max_date'
id = models.IntegerField(default=0, primary_key=True)
timestamp = models.DateTimeField(default=timezone.now, db_index=True)
但是有一些问题:
即使 Managed = False './manage.py makemigrations' 仍会为此表创建迁移。 我什至尝试将迁移留在那里,但用原始 SQL 替换模型来创建 View 但运气不佳。
我现在需要执行 select_lated 来连接两个表并进行查询,但我应该怎么做?
我在 SampleModel 上尝试了一个外键,如下所示:
by_date = models.ForeignKey(SampleModelWithMaxDate, null=True)
但这也不起作用:
操作错误:(1054,“‘字段列表’中存在未知列‘no_chain_sample_model_with_max_date.by_date_id’”)
所以总的来说,我什至不确定是否可能,我可以看到其他人正在使用带有 View 的模型,并且只是为了查询也适合我的独立模型,但是是否有可能做比这更聪明的事情?
谢谢
最佳答案
我找不到任何 ORM 方法来在一个查询中获取您想要的内容,但我们可以通过两个查询来完成此操作:
首先,我们获取所有用户的最大时间戳
latest_timestamps = SampleModel.objects.values('user_id')
.annotate(max_ts=Max('timestamp')).values('max_ts')
此处 values(user_id)
用作 group by
操作。
现在,我们获得了具有精确时间戳的 SampleModel
的所有实例
qs = SampleModel.objects.filter(timestamp__in=latest_timestamps)
<小时/>
PostgreSQL 具体答案:
你可以混合order_by
和 distinct
实现你想要的:
SampleModel.objects.order_by('user_id', '-timestamp').distinct('user_id')
分解:
# order by user_id, and in decreasing order of timestamp
qs = SampleModel.objects.order_by('user_id', '-timestamp')
# get distinct rows using user_id, this will make sure that the first entry for
# each user is retained and since we further ordered in decreasing order of
# timestamp for each user the first entry will have last row added
# for the user in the database.
qs = qs.distinct('user_id')
关于python - 为 MySQL View 创建模型并加入它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36644624/