If you're using Postgres, you can use DISTINCT ON
( distinct
) on device_id
:
(如果您使用的是Postgres,则可以在device_id
上使用DISTINCT ON
( distinct
):)
from django.db.models import F
StatusActivity.objects.order_by('device_id', '-modified_at').distinct('device_id').annotate(
ID=F('device_id__id'),
device_name=F('device_id__device_name'),
).values('ID', 'device_name', 'status', 'modified_at')
If you don't have Postgres, you can use subqueries for annotating the data from StatusActivity
:
(如果您没有Postgres,则可以使用子查询来注释StatusActivity
的数据:)
from django.db.models import Subquery, OuterRef
Device.objects.annotate(
status=Subquery(
StatusActivity.objects.filter(
device_id=OuterRef('pk')
).order_by('-modified_at').values('status')[:1]
),
modified_at=Subquery(
StatusActivity.objects.filter(
device_id=OuterRef('pk')
).order_by('-modified_at').values('modified_at')[:1]
),
).values('id', 'device_name', 'status', 'modified_at')
Caveats:
(注意事项:)
-
Subquery
requires only one row and column so that the value can be used in the annotation. (Subquery
仅需要一行和一列,以便可以在注释中使用该值。)
This means if we want to have multiple columns from a subquery, we need to use two annotations so there would be two joins like above so there would be a performance hit. (这意味着,如果我们想从一个子查询中获得多个列,则需要使用两个注释,以便像上面那样有两个联接,这样会影响性能。)
- If you want, you can limit your annotations to only one field eg
status
but if you want both of the fields I would recommend the first approach (assuming you're using a supported DB (Postgres)). (如果需要,可以将注释限制为仅一个字段,例如status
但是如果要两个字段,我建议采用第一种方法(假设您使用的是受支持的数据库(Postgres))。)
Also note that Django automatically appends _id
to the FK fields, so it's preferable to name them without any _id
suffix.
(还要注意,Django会自动将_id
附加到FK字段,因此最好将它们命名为不带任何_id
后缀。)
In your case, use device
instead of device_id
. (在您的情况下,请使用device
而不是device_id
。)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…