在Django ORM中透视数据和复杂注释

ros*_*ssp 13 python sql django django-orm

Django中的ORM让我们可以根据相关数据轻松地对查询集进行注释(添加字段),但是我找不到为不同过滤的相关数据子集获取多个注释的方法.

这是与django-helpdesk有关的问题,django-helpdesk是一个开源的Django驱动的故障单跟踪器.为了图表和报告的目的,我需要像这样转动数据

考虑这些模型:

CHOICE_LIST = (
    ('open', 'Open'),
    ('closed', 'Closed'),
)

class Queue(models.model):
    name = models.CharField(max_length=40)

class Issue(models.Model):
    subject = models.CharField(max_length=40)
    queue = models.ForeignKey(Queue)
    status = models.CharField(max_length=10, choices=CHOICE_LIST)
Run Code Online (Sandbox Code Playgroud)

而这个数据集:

队列:

ID | Name
---+------------------------------
1  | Product Information Requests
2  | Service Requests
Run Code Online (Sandbox Code Playgroud)

问题:

ID | Queue | Status
---+-------+---------
1  | 1     | open
2  | 1     | open
3  | 1     | closed
4  | 2     | open
5  | 2     | closed
6  | 2     | closed
7  | 2     | closed
Run Code Online (Sandbox Code Playgroud)

我想看一个注释/聚合看起来像这样:

Queue ID | Name                          | open | closed
---------+-------------------------------+------+--------
1        | Product Information Requests  | 2    | 1
2        | Service Requests              | 1    | 3
Run Code Online (Sandbox Code Playgroud)

这基本上是一个交叉表或数据透视表,用Excel的说法.我目前正在使用一些自定义SQL查询构建此输出,但是如果我可以使用Django ORM,我可以更轻松地动态过滤数据,而无需在我的SQL中进行狡猾的WHERE子句插入.

对于"奖励积分":如何在枢轴字段(status在上面的示例中)是日期,并且我们希望列为月/周/季度/天?

S.L*_*ott 5

你有Python,使用它.

from collections import defaultdict
summary = defaultdict( int )
for issue in Issues.objects.all():
    summary[issue.queue, issue.status] += 1
Run Code Online (Sandbox Code Playgroud)

现在,您的summary对象具有队列,状态为两元组密钥.您可以使用各种模板技术直接显示它.

或者,如果更简单,您可以将其重组为类似表格的结构.

table = []
queues = list( q for q,_ in summary.keys() )
for q in sorted( queues ):
    table.append( q.id, q.name, summary.count(q,'open'), summary.count(q.'closed') )
Run Code Online (Sandbox Code Playgroud)

你有很多很多Python技术来做透视表.

如果你测量,你可能会发现像这样的大多数Python解决方案实际上比纯SQL解决方案更快.为什么?映射可以比SQL算法更快,SQL算法需要排序作为GROUP-BY的一部分.

  • 如果"问题"表很大并且很难被视为一般,那么此解决方案将崩溃​​. (2认同)