使用Django 1.7,Python 3.4和PostgreSQL 9.1我在查询集上注释时遇到了困难。 这是我的模特:
class Payment(models.Model):
TYPE_CHOICES= (
('C', 'CREDIT'),
('D', 'DEBIT')
)
amount = models.DecimalField(max_digits=8, decimal_places=2, default=0.0)
customer = models.ForeignKey(Customer, null=False)
type=models.CharField(max_length=1, null=True, choices=TYPE_CHOICES)
class Customer(models.Model):
name = models.CharField(max_length=100, unique=True)
available_funds = models.DecimalField(max_digits=8, decimal_places=2, null=True, default=0.0)
total_funds = models.DecimalField(max_digits=8, decimal_places=2, null=True, default=0.0)
我想要的是:
Customers:
Name | Total in | Total out | available funds | total funds
-----------------------------------------------------------------
cust 1 | 255 | 220 | 5 | 35
cust 2 | 100 | 120 | 0 | -20
cust 3 | 50 | 20 | 15 | 30
和一些数据:
Payments:
amount | customer | type
--------------------------
20 | cust 1 | D
10 | cust 1 | c
70 | cust 2 | D
20 | cust 2 | C
10 | cust 2 | D
25 | cust 1 | C
200 | cust 3 | D
10 | cust 3 | C
20 | cust 1 | D
我正在尝试此查询集:
Customer.objects.select_related().filter(Q(payment__isnull=False)& Q(payment__type='D')).values('name').annotate(Sum('payment__amount'))
但我只得到借记。 我不知道如何创建包含客户,总计,总计,总资金,可用资金的列表。
任何人都可以帮我吗?
答案 0 :(得分:0)
我认为您对使用单个查询集可以执行的操作有限制。我这样说的原因是你要求在不同的Payment
条记录集上进行数据库聚合。
让我们看一下您当前的查询集:
Customer.objects.select_related().filter(Q(payment__isnull=False)& Q(payment__type='D')).values('name').annotate(Sum('payment__amount'))
忽略无关的Q()
来电,过滤电话payment__type='D'
表示payment_amount将始终仅与借记相关。如果您将其更改为“C”,它将始终仅与学分相关。此查询演示了Django的查询集语言强加给您的基本约束 - 您无法真正生成两个不同的聚合并将它们注释到单个记录中。
绕过原始的SQL土地来看看我如何编写这个查询是另一种证明这一点的方法。当然,您会注意到我仍在运行两个不同的Payment
聚合!一个用于学分,一个用于借记。
SELECT
*
FROM
customer
INNER JOIN
(
SELECT SUM(amount) as total FROM Payment WHERE type='C' GROUP BY customer_id, type
) AS credits
ON credits.customer_id=customer.id
INNER JOIN
(
SELECT SUM(amount) as total FROM Payment WHERE type='D' GROUP BY customer_id, type
) AS debits
ON debits.customer_id=customer.id
该查询将返回大致形式的数据:
customer.id | customer.name | ... | credits.total | debits.total
----------------------------------------------------------------
1 | foo bar | | 20 | 30
2 | baz qux | | 30 | 20
如果您尝试仅使用一个内部联接/聚合,则您必须按付款类型和客户分组,从而产生如下表格:
customer_id | type | sum(amount)
--------------------------------
1 | C | 20
1 | D | 30
2 | C | 30
2 | D | 20
当您将这个中间结果与您的客户联系起来时,应该立即明确说明借方和贷方仍未统一到单个记录中。
因为你不能在Django中使用内连接进行这种选择(据我所知),你不能真正做你想在单个查询中做的事情。但是,您的问题有解决方案。
按照可取性的降序排列(我认为当然 - 并且基于我认为结果代码的显而易见性/可维护性),首先是只做多个查询并手动统一结果。
您还可以将信用/借记作为Customer
记录的一部分进行跟踪。您已经以这种方式跟踪可用资金(您在查询中使用F
个对象来更新/维护这些记录,对吧?),因此维护类似的信用卡/借记卡摘要并不是真的太繁重了时尚也是如此。
最后,我认为你不应该这样做,因为我认为不需要这样做,你可以执行原始的SQL查询来一次性获得所需的结果。