Расчет суммы по двум группам без использования двух наборов запросов? - PullRequest
0 голосов
/ 17 мая 2019

Я довольно новичок в Django & Python ..

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

Первое решение, которое у меня было в голове, это, конечно, отправить два запроса в БД, чтобы получить сумму один раз для всех категорий каждой транзакции, а затем сгруппировать по родительской категории:

main_qs = Transaction.objects.values('category__parent').annotate(credits=Sum('credit')).annotate(debits=Sum('debit')).filter(category__isnull=False)
sub_qs = Transaction.objects.values('category').annotate(credits=Sum('credit')).annotate(debits=Sum('debit')).filter(category__isnull=False)

это нарушает DRY, поэтому я сделал это в одном запросе и обнаружил тег шаблона перегруппировки, который использовал для перегруппировки QS на основе родительской категории.

VIEW

category_qs = Transaction.objects.values('category__parent','category').annotate(credits=Sum('credit')).annotate(debits=Sum('debit')).filter(category__isnull=False)

context = {
        'active': 'statistics',
        'query' : category_qs,
    }
return render(request, 'stats.html', context)

QUERY

SELECT categories.parent_id, transactions.category_id, CAST(SUM(transactions.credit) AS NUMERIC) AS credits, CAST(SUM(transactions.debit) AS NUMERIC) AS debits 
FROM transactions INNER JOIN categories 
ON (transactions.category_id = categories.id) 
WHERE transactions.category_id IS NOT NULL 
GROUP BY categories.parent_id, transactions.category_id

╭───╥───────────┬─────────────┬─────────┬────────╮
│   ║ parent_id │ category_id │ credits │ debits │
╞═══╬═══════════╪═════════════╪═════════╪════════╡
│ 1 ║     1     │      5      │    0    │   15   │
│ 2 ║     9     │     11      │ 1220.34 │    0   │
│ 3 ║    22     │     23      │    0    │   35   │
│ 4 ║    22     │     24      │    0    │   39   │
│ 5 ║    22     │     25      │    0    │79.99   │
│ 6 ║    43     │     44      │    0    │  300   │
│ 7 ║    65     │     66      │    0    │  115   │
│ 8 ║    82     │     85      │  200    │   15   │
└───╨───────────┴─────────────┴─────────┴────────┘

ШАБЛОН

<!-- stats.html -->
{% regroup query by category__parent as main_categories %}

<ul>
  {% for main_category,groups in main_categories %}
  <li data-toggle="collapse" data-target="#subcategories_{{main_category.id}}">
{{main_category.name}} || TOTAL: ??? 
    <ul class="collapse" id="subcategories_{{main_category.id}}">
    {% for group in groups %}
    {% with group.credits|sub:group.debits as amount %}
      <li>{{group.category.name}} >> {{ amount }} ({{group.credits}}, {{group.debits</li>
    {% endfor %}
    </ul>
  </li>

  {% endfor %}
</ul>

Это, конечно, дает мне правильную сумму для каждой категории, однакоМне также нужна сумма родительской категории, в которой в этом случае отсутствует общая сумма категории 22, поскольку она появляется 3 раза.

Я не знаю, сможете ли вы достичь этого с помощью ORM django или вам нужноотправить RAW sql в БД или если вам нужно сделать это вручную в python после или если вам действительно нужно отправить 2 запроса в БД для каждой группировки?

...