python - 为 MySQL View 创建模型并加入它

标签 python mysql django orm

我正在做一些原型(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)

但是有一些问题:

  1. 即使 Managed = False './manage.py makemigrations' 仍会为此表创建迁移。 我什至尝试将迁移留在那里,但用原始 SQL 替换模型来创建 View 但运气不佳。

  2. 我现在需要执行 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_bydistinct实现你想要的:

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/

相关文章:

python - 在哪里可以下载带有 psycopg2 for Windows 的二进制鸡蛋?

python - 如何将(时间戳,值)数组转换为时间序列

php - Laravel 5.5 groupBy 与总和和第一个选项

mysql - 在连接上使用计数 - MYSQL

python - 将自定义查询集传递给 Django Rest Framework 中的序列化程序

python - 将列表转换为 'transposed' 列表

python - 如何将列表输出全部保留在一行上,而不包含下一行代码

php - 用户名验证不起作用

javascript - Django 使用 VueJS 的上下文进行渲染

python - ListAPIView 中的 Django Rest Framework 序列化错误