Как использовать Django Orm Subqueries в этом sql - PullRequest
0 голосов
/ 26 марта 2019

Я новичок в Django ORM, и мне было трудно использовать подзапросы Django в этом операторе sql, поскольку я не нашел вложенный select .. from (select... пример в django orm:

это мои модели:

class A:
     published_at = models.DateTimeField(_('Published at'))
     ....

Class B:

     pub=models.ForeignKey('A', verbose_name=_('A'), blank=True, null=True,
                          on_delete=models.SET_NULL)
     prices= models.FloatField(_('Price'), blank=True, null=True, db_index=True)
     soc = models.IntegerField(_('SOC'), blank=True, null=True,
                               db_index=True)

и это SQL

select DATE_FORMAT(`A`.`published_at`, '%Y-%m-%d'), sum(b)
    from (
   select `B`.`pub_id` as c, soc, avg(prices) as b
   from B
   group by c, soc
    ) as ch
   INNER JOIN `A` ON (c = `A`.`id`)
   group by DATE_FORMAT(`A`.`published_at`, '%Y-%m-%d');

является ли использование `подзапросов в этой ситуации полезным? Я использую Django 1.11

помогите пожалуйста

Обновление

Когда я попробовал решение, предложенное Endre Both, я получил эту ошибку

           Traceback (most recent call last):
      File "/home/vagrant/.local/lib/python3.6/site- 
       packages/IPython/core/interactiveshell.py", line 3296, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
        File "<ipython-input-7-824230af12bd>", line 5, in <module>
.annotate(total=Sum('avg'))
      File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/query.py", line 948, in annotate
clone.query.add_annotation(annotation, alias, is_summary=False)
      File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 973, in add_annotation
summarize=is_summary)
       File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/aggregates.py", line 19, in resolve_expression
c = super(Aggregate, self).resolve_expression(query, allow_joins, reuse, summarize)
     File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/expressions.py", line 548, in resolve_expression
c.source_expressions[pos] = arg.resolve_expression(query, allow_joins, reuse, summarize, for_save)
      File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/expressions.py", line 471, in resolve_expression
return query.resolve_ref(self.name, allow_joins, reuse, summarize)
        File "/home/vagrant/.local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1472, in resolve_ref
return self.annotation_select[name]
    KeyError: 'avg'

1 Ответ

0 голосов
/ 27 марта 2019

Если вы сначала хотите рассчитать средние цены по pub_id и soc, а затем суммировать те средние значения для пабов с одинаковой датой публикации, возможно, вы ищете это:

from django.db.models import FloatField, OuterRef, Subquery, Sum, Avg

sq = Subquery(B.objects
               .filter(pub_id=OuterRef('id'), soc=OuterRef('b__soc'))
               .values('pub_id', 'soc')
               .annotate(avg=Avg('prices'))
               .values('avg'),
              output_field=FloatField()
             )

results = (A.objects
            .values('id', 'published_at', 'b__soc')
            .annotate(avg=sq)
            .values('published_at')
            .annotate(total=Sum('avg'))
           )

Написав это вслепую, мне любопытно, правильно ли я понял.Это может быть одним из тех случаев, когда необработанный запрос SQL легче понять.

Кстати, какая польза от суммирования средних значений без какого-либо взвешивания?

...