Django - 获取每个查询结果的最新记录

时间:2015-10-29 17:11:24

标签: python mysql django

我不确定这是否可以在单个查询中完成。我的模型看起来像这样:

class TestStatus(models.Model):
    id = models.AutoField(primary_key=True)
    build = models.CharField(max_length=20)
    test_name = models.CharField(max_length=50)
    test_status = models.CharField(max_length=10)
    test_start = models.DateTimeField(auto_now=True)
    test_end = models.DateTimeField(null=True)

该表旨在存储针对给定构建号的自动化测试运行的结果。我要做的是查询所有测试及其针对给定构建运行的状态,但在某些情况下,同一测试运行多次。此查询返回给定构建的所有测试:

TestStatus.objects.filter(build__exact='1.2.3.4')

但是如果同一个测试不止一次运行,那么我会得到这样的结果:

-------------------------------------------------
| test_name | test_status | test_start          |
-------------------------------------------------
| Test1     | FAIL        | 2015-10-28 14:20:56 |
| Test2     | PASS        | 2015-10-28 14:23:14 |
| Test1     | PASS        | 2015-10-28 15:21:24 |
-------------------------------------------------

我想要返回的内容仅是针对给定test_status的每次test_name投放的最新build。我知道我可以在MAX()字段上执行test_start但只返回一个条目,因为它查看了查询集中所有字段的最大日期值。我可以进行查询,然后如果有任何失败的测试,则执行另一个查询以查看给定的test_name是否有更新的测试条目,但如果可以,我宁愿避免多次查询。

我希望通过一个查询获得这样的输出:

-------------------------------------------------
| test_name | test_status | test_start          |
-------------------------------------------------
| Test2     | PASS        | 2015-10-28 14:23:14 |
| Test1     | PASS        | 2015-10-28 15:21:24 |
-------------------------------------------------

我只是在针对给定版本进行最新的测试运行。有什么想法吗?

修改

以下是我尝试过的其他一些事情(第一个是另一个答案建议的):     TestStatus.objects.annotate(max_date = Max('test_start'))。filter(test_start = F('max_date'),build ='1.2.3.4')

但是返回的结果与TestStatus.objects.filter(build='1.2.3.4')

相同

我一直在玩其他答案中发布的一些SQL,但是当我尝试按build过滤时,此查询(似乎可以解决我的问题)不会返回任何内容:

SELECT a.*
FROM test_status a
INNER JOIN(
    SELECT test_name, MAX(test_start) AS max_date
    FROM test_status
    GROUP BY test_name) b
ON a.test_name = b.test_name
AND a.test_start = b.max_date
WHERE build = '1.2.3.4';

1 个答案:

答案 0 :(得分:0)

尝试:

tests = TestStatus.objects.filter(build__iexact='1.2.3.4',test_status=True).order_by('test_name','-test_start').distinct('test_name')

更新:刚看到mysql标签, distinct([* fields])仅适用于PostgresSQL