Джанго 1.8.Когда мы используем поле id в значениях и аннотируем операцию в django, в результате sql-запроса игнорируются другие поля - PullRequest
0 голосов
/ 24 февраля 2019

Я хочу обновить Django с 1.7.11 до 1.11.18.Но я нашел проблему.Django делает разные sql-запросы для разных версий Django.Например.У меня есть запрос:

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', )

sql-запрос для Django 1.7.11:

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 поля: id , имя , payment_gateway .

Но у нас есть следующий sql-запрос для Django 1.8.19:

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 ?Это главный вопрос.

НО, когда я удаляю поле id из секции values Django 1.8 делает правильный sql-запрос:

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

1 Ответ

0 голосов
/ 25 февраля 2019

В последних версиях Django избыточные поля отсутствуют в предложении group by.Если вы группируете по уникальному полю в таблице, нет смысла группировать по любым другим полям из этой таблицы.Это определенно объясняет пропуск member_account.name, который является избыточным, если в запросе есть уникальный member_account.id.

То же самое может быть верно для payment_gateway , если , у вас есть ограниченияс тем, чтобы на каждом счете была только одна payment_gateway.Если на счетах может быть несколько платежных шлюзов, я не вижу непосредственного объяснения того, почему Django считает это поле избыточным для group_by целей.

Если вы покажете определения соответствующих моделей, мы можем сообщить вамбольше.

...