如何将含array_agg的关联查询SQL转换为Django Queryset?
用Django QuerySet实现等价SQL查询
前提假设
先假设你的Django模型定义如下(对应SQL中的表和字段):
from django.db import models from django.contrib.postgres.aggregates import ArrayAgg class S2Followers(models.Model): id_s2_users = models.IntegerField() id_s2_users1 = models.IntegerField() id_s2_user_status = models.IntegerField() class Meta: db_table = 's2_followers' class S2Post(models.Model): id = models.IntegerField(primary_key=True) id_s2_users = models.IntegerField() id_s2_post_status = models.IntegerField() class Meta: db_table = 's2_post'
QuerySet实现代码
queryset = S2Followers.objects.filter( id_s2_user_status=1, s2post__id_s2_post_status=1 # 过滤关联的Post状态,对应SQL中WHERE的sp.id_s2_post_status=1 ).values( 'id_s2_users' # 指定分组字段,对应SQL的GROUP BY sf.id_s2_users ).annotate( post_ids=ArrayAgg('s2post__id') # 聚合关联Post的id,对应SQL的array_agg(sp.id) )
关键说明
- 过滤逻辑:
filter中的id_s2_user_status=1直接对应SQL里的sf.id_s2_user_status=1;s2post__id_s2_post_status=1利用Django的反向关联规则(默认以模型名小写加_set,这里简化为s2post__)过滤关联数据,等价SQL中对sp表的状态过滤。 - 分组设置:
values('id_s2_users')会让QuerySet按该字段分组,完全对应SQL的GROUP BY sf.id_s2_users。 - 聚合函数:
ArrayAgg是Django针对PostgreSQL提供的内置聚合函数,直接匹配SQL的array_agg,需要从django.contrib.postgres.aggregates导入。如果使用其他数据库(如MySQL),需替换为对应函数(比如GroupConcat)。
优化建议(可选)
如果给模型添加显式外键关联,代码会更简洁易读:
class S2Post(models.Model): # ...其他字段 follower = models.ForeignKey( S2Followers, on_delete=models.CASCADE, db_column='id_s2_users', related_name='posts' )
此时QuerySet可调整为:
queryset = S2Followers.objects.filter( id_s2_user_status=1, posts__id_s2_post_status=1 ).values('id_s2_users').annotate(post_ids=ArrayAgg('posts__id'))
内容的提问来源于stack exchange,提问作者Mahendra
相关产品推荐
相关产品推荐

