【发布时间】:2016-01-29 23:15:20
【问题描述】:
我不确定这是否可以在单个查询中完成。我有一个看起来像这样的模型:
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 |
-------------------------------------------------
我想要返回的只是针对给定build 运行的每个test_name 的最新test_status。我知道我可以在test_start 字段上执行MAX(),但它只返回一个条目,因为它正在查看查询集中所有字段的最大日期值。我可以做一个查询,然后如果有任何失败的测试做另一个查询,看看是否有给定的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';
【问题讨论】:
-
你的意思是:TestStatus.object.filter(build__exact='1.2.3.4').latest('test_start')
-
只返回给定查询中的最新记录(即只有一条记录),但我想查看查询集中所有记录的最新记录。
-
仅供参考,您无需将 id 定义为自动字段...django does that for you.
-
@stimko68 检查
latestQuerySet 运算符。