Django计算组内的百分比

时间:2018-05-03 09:52:57

标签: django python-3.x postgresql

我有一个模型,我想对两个值执行分组,并计算每个外部分组的每个值的百分比。

目前我只是进行查询以获取所有行并将它们放入pandas数据帧并执行类似于answer here的操作。虽然这有效但我确信如果我能让查询直接返回我需要的信息会更有效。

我目前正在使用Django 2.0.5

上的后端数据库运行PostgreSQL 9.6.8

我认为窗口函数可以作为indicated here的解决方案,但我无法构建annotatevalues的成功组合来为我提供所需的输出。

如果我能找到一种方法将摘要行作为每行的一组额外列,可以在rollup中引入另一种可能的解决方案PostgreSQL 9.5吗?但我也认为Django尚未支持它。

型号:

class ModelA(models.Model):
    grouper1 = models.CharField()
    grouper2 = models.CharField()
    metric1 = models.IntegerField()

所有行:

grouper1 | grouper2 | metric1
---------+----------+---------
   A     |    C     |    2   
   A     |    C     |    2   
   A     |    C     |    2   
   A     |    D     |    4   
   A     |    D     |    4   
   A     |    D     |    4   
   B     |    C     |    5   
   B     |    C     |    5   
   B     |    C     |    5   
   B     |    D     |    6   
   B     |    D     |    4   
   B     |    D     |    5   

期望的输出:

grouper1 | grouper2 | sum(metric1) | Percentage 
---------+----------+--------------+-----------
   A     |    C     |    6         |    40
   A     |    D     |    12        |    60
   B     |    C     |    15        |    50
   B     |    D     |    15        |    50

我接近我的预期

ModelA.objects.all(
    ).values(
        'grouper1', 
        'grouper2'
    ).annotate(
        SumMetric1=Window(expression=Sum('metric1'), partition_by=[F('grouper1'), F('grouper2')]), 
        GroupSumMetric1=Window(expression=Sum('metric1'), partition_by=[F('grouper1')])
)

但是,这会为数据库中的每个原始行返回一行,如下所示:

grouper1 | grouper2 | sum(metric1) | Percentage 
---------+----------+--------------+-----------
   A     |    C     |    6         |    40
   A     |    C     |    6         |    40
   A     |    C     |    6         |    40
   A     |    D     |    12        |    60
   A     |    D     |    12        |    60
   A     |    D     |    12        |    60
   B     |    C     |    15        |    50
   B     |    C     |    15        |    50
   B     |    C     |    15        |    50
   B     |    C     |    15        |    50
   B     |    C     |    15        |    50
   B     |    D     |    15        |    50 

1 个答案:

答案 0 :(得分:1)

在这种情况下.distinct()可能会有所帮助 更多信息是here

相关问题