django,count和sum查询

时间:2015-12-17 07:58:35

标签: sql django orm django-queryset

用户可以创建邀请。

其他用户可以接受邀请。

我想计算每个邀请者的接受用户总数(user_invite)

Invitation

id, user_invite
-----------------
1,  a     
2,  a     
3,  a     
4,  b     
5,  b     

InvitationAccept

invitation, user_accept
-----------------
1,              c
1,              d
2,              e
4,              f

我想

user_invite,    accept_count
----------------------------
a                       3 (c,d,e)
b                       1 (f)

Django orm看起来像

class Invitation:
    user_invite = models.ForeigneKey(settings.AUTH_USER_MODEL)
    invite_at = models.DateTimeField()
    accepts = generic.GenericRelation(InvitationAccept)

class InvitationAccept:

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    invitation = generic.GenericForeignKey('content_type', 'object_id')

    user_accept = models.ForeignKey(settings.AUTH_USER_MODEL)

这样做的原因是什么?和sql等价?

2 个答案:

答案 0 :(得分:0)

我不知道您使用的数据库,所以我在MS SQL-SERVER

中尝试了这个
    select a.user_invite,cast(COUNT(1) as varchar) + '(' + ' ' +
    (STUFF((select ',' + user_accept from (select * from Invitation inv inner join InvitationAccept apct on inv.id = apct.invitation) b
    where b.user_invite=a.user_invite FOR XML PATH('')),1,1,'')) + ' ' + ')' as accept_count
    from (select * from Invitation inv inner join InvitationAccept apct on inv.id = apct.invitation) a
    group by a.user_invite

如果您使用的是Oracle,请尝试使用其他函数concat_ws()来替换stuff部分和||替换+。

答案 1 :(得分:0)

如果您使用的是MySQL,则可以使用GROUP_CONCATLEFT OUTER JOIN返回0 ()以查看不匹配的邀请:

SELECT i.user_invite,
   CONCAT(COUNT(ia.invitation), ' (',
          GROUP_CONCAT(user_accept ORDER BY user_accept),')') AS accept_count
FROM Invitation i
LEFT JOIN InvitationAccept ia
  ON i.id = ia.invitation
GROUP BY i.user_invite;

SqlFiddleDemo

输出:

╔══════════════╦══════════════╗
║ user_invite  ║ accept_count ║
╠══════════════╬══════════════╣
║ a            ║ 3 (c,d,e)    ║
║ b            ║ 1 (f)        ║
╚══════════════╩══════════════╝

修改

  

实际上我只需要计数,(c,d,e)仅用于解释。

现在代码是可移植的并且与ANSI兼容。它适用于大多数RBDMS。

SELECT i.user_invite, COUNT(ia.invitation) AS accept_count
FROM Invitation i
LEFT JOIN InvitationAccept ia
  ON i.id = ia.invitation
GROUP BY i.user_invite;