首页 > 解决方案 > 姜戈 1.8。当我们在值中使用 id 字段并在 django 中注释操作时,结果 sql-query 中会忽略其他字段

问题描述

我想将 Django 从 1.7.11 更新到 1.11.18。但是我发现了一个问题。Django 对不同的 Django 版本进行不同的 sql 查询。例如。我有一个查询:

Account.objects
       .values('id', 'name', invoice__payment__payment_gateway')
       .annotate(
         pay_paid=Sum('invoice__payment__amount'),
         pay_refunded=Sum('invoice__payment__amount_refunded')
       )
       .order_by('-name', )

Django 1.7.11 的 sql 查询:

SELECT `member_account`.`id`, 
       `member_account`.`name`, 
       `member_payment`.`payment_gateway`, 
       SUM(`member_payment`.`amount_refunded`) AS `pay_refunded`, 
       SUM(`member_payment`.`amount`) AS `pay_paid` 
FROM `member_account` 
  LEFT OUTER JOIN `member_invoice` ON ( `member_account`.`id` = `member_invoice`.`account_id` ) 
  LEFT OUTER JOIN `member_payment` ON ( `member_invoice`.`id` = `member_payment`.`invoice_id` ) 
GROUP BY `member_account`.`id`, `member_account`.`name`, `member_payment`.`payment_gateway` 
ORDER BY `member_account`.`name` DESC

请注意该GROUP BY部分。有 3 个字段:idnamepayment_gateway

但是对于 Django 1.8.19,我们有以下 sql-query:

SELECT `member_account`.`id`, 
       `member_account`.`name`, 
       `member_payment`.`payment_gateway`, 
       SUM(`member_payment`.`amount_refunded`) AS `pay_refunded`, 
       SUM(`member_payment`.`amount`) AS `pay_paid` 
FROM `member_account` 
  LEFT OUTER JOIN `member_invoice` ON ( `member_account`.`id` = `member_invoice`.`account_id` ) 
  LEFT OUTER JOIN `member_payment` ON ( `member_invoice`.`id` = `member_payment`.`invoice_id` ) 
GROUP BY `member_account`.`id` 
ORDER BY `member_account`.`name` DESC

我们在该GROUP BY部分中只有一个字段。为什么我们只有一个id字段?这是主要问题。

但是当我从 Django 1.8 部分中删除id字段时,values会生成有效的 sql-query:

SELECT `member_account`.`name`, 
       `member_payment`.`payment_gateway`, 
       SUM(`member_payment`.`amount_refunded`) AS `pay_refunded`, 
       SUM(`member_payment`.`amount`) AS `pay_paid` 
FROM `member_account` 
  LEFT OUTER JOIN `member_invoice` ON ( `member_account`.`id` = `member_invoice`.`account_id` ) 
  LEFT OUTER JOIN `member_payment` ON ( `member_invoice`.`id` = `member_payment`.`invoice_id` ) 
GROUP BY `member_account`.`name`, `member_payment`.`payment_gateway` 
ORDER BY `member_account`.`name` DESC

标签: pythondjangogroup-byannotate

解决方案


最近的 Django 版本似乎从group by子句中省略了冗余字段。如果您按表中的唯一字段进行分组,则按该表中的任何其他字段进行分组是没有意义的。这绝对解释了 的省略member_account.name,如果您member_account.id在查询中有唯一性,这是多余的。

如果payment_gateway 对每个帐户只能有一个payment_gateway. 如果帐户可以有多个支付网关,那么我看不出为什么 Django 认为该字段是多余的group_by

如果您显示相关模型的定义,我们可能会告诉您更多信息。


推荐阅读