一尘不染

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

sql

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)

而这个数据集:

队列:

ID | Name
---+------------------------------
1  | Product Information Requests
2  | Service Requests

问题:

ID | Queue | Status
---+-------+---------
1  | 1     | open
2  | 1     | open
3  | 1     | closed
4  | 2     | open
5  | 2     | closed
6  | 2     | closed
7  | 2     | closed

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

Queue ID | Name                          | open | closed
---------+-------------------------------+------+--------
1        | Product Information Requests  | 2    | 1
2        | Service Requests              | 1    | 3

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

对于“加分点”:如果枢轴字段(status在上面的示例中)是一个日期,而我们希望这些列是月/周/季度/天,那么该怎么做呢?


阅读 209

收藏
2021-03-17

共1个答案

一尘不染

您有Python,请使用它。

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

现在,您的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') )

您有很多用于做数据透视表的Python技术。

如果进行测量,您可能会发现,这样的以Python为主的解决方案实际上比纯SQL解决方案要快。为什么?映射可能比需要在GROUP-BY中进行排序的SQL算法更快。

2021-03-17