Как выбрать данные из набора запросов и сгруппировать по количеству на определенную дату - PullRequest
0 голосов
/ 23 мая 2019

Когда я запрашиваю свою базу данных, я получаю одну и ту же запись три раза с тремя разными значениями. В списке результатов я хотел бы получить только одну запись, показывающую сумму этих подсчетов.

То, что я хотел бы отобразить, это общая сумма за определенный период.

В моем запросе я ввожу даты (от - до), метрический тип, тип данных и год публикации.

Например, я на веб-сайте, когда я ввожу

from 201903 until 201905 

Я получаю три заголовка, к которым обращались в этот период, а также сколько раз к ним обращались.

Title, Publisher,    DOI,   data_type,YOP,[some other stuff] Counts

Title A  publisherA   1234    Article, 2006, [some_other_stuff], 3
Title A  publisherA   1234    Article, 2006, [some_other_stuff], 5
Title A  publisherA   1234    Article, 2006, [some_other_stuff], 3

Мне нужно что-то вроде

Title, publisher, DOI,   data_type, YOP,  [some_other_stuff],  Total period

Title A, publisherA 1234   Article, 2006,   [some_other_stuff],    11


В views.py у меня есть следующий код:

    q_report = Q()


        var0 = self.request.GET.get("period1", "")
        var1 = self.request.GET.get("period2", "")
        var2 = self.request.GET.get("metric_type", "")
        var3 = self.request.GET.get("data_type", "")
        var4 = self.request.GET.get("YOP", "")



        if var0:
            q_report = q_report & (Q(month__gte=var0) & Q(month__lte=var1) )
            #q_report_count = q_report_count & (Count(month__gte=var0) & Count(month__lte=var1) )
        if var2:
            q_report = q_report & (Q(metric_type=var2))
            #q_report_count = q_report_count & (Q(metric_type=var2))
        if var3:
             q_report = q_report & (Q(data_type=var3))
        if var4:
             q_report = q_report & (Q(YOP=var4))

Если я использую

qs = self.model.objects.filter(q_report).select_related()

Я верну три записи

Результат

<QuerySet [<Model: Title A>, <Model: Title A>, <Model: Title A>]>

Я могу легко рассчитать сумму, используя

total = self.model.objects.aggregate(total=Sum('counts', filter=q_report))

Результат

{total : 11.0}

Но в идеале мне нужно получить и другие значения

Прямо сейчас я не могу понять, как я могу собрать их вместе, то есть что-то вроде


<QuerySet [<Model: {'title':Title A, 'total':11}>, Model: {'title':Title B, 'total':7}>]

Я даже не знаю, возможно ли это или желательно. Но мне нужно вернуть набор запросов и сумму.

Кто-нибудь может помочь? Спасибо.

Ответы [ 2 ]

1 голос
/ 23 мая 2019

По сути, это проблема моделирования. Вместо определения модели, например:

# modeling with data duplication

class SomeModel(models.Model):
    title = models.CharField(max_length=256)
    publisher = models.CharField(max_length=256)
    doi = models.CharField(max_length=256)
    publication_type = models.CharField(max_length=128)
    year = models.IntegerField()
    date = models.DateField()
    counts = models.IntegerField()

Вы должны сделать модель типа Publication и связать SomeModel с этим Publication, например:

# modeling without data duplication

class <b>Publication</b>(models.Model):
    title = models.CharField(max_length=256)
    publisher = models.CharField(max_length=256)
    doi = models.CharField(max_length=256)
    publication_type = models.CharField(max_length=128)
    year = models.IntegerField()

class PublicationSale(models.Model):
    <b>publication = models.ForeignKey(Publication, on_delete=models.CASCADE)</b>
    date = models.DateField()
    counts = models.IntegerField()

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

В этом случае вы можете запросить как:

from django.db.models import Sum

Publication.objects.annotate(
    <b>total=Sum('publication_sale__counts')</b>
)

Затем вы получаете QuerySet с Publication объектами, которые имеют дополнительный атрибут .totals, который является суммой counts связанных PublicationSale объектов.

Если вы не выполните эту модернизацию, вы можете работать с:

from django.db.models import <b>Sum</b>

qs = self.model.objects.filter(q_report).values(
    'title', 'publisher', 'doi', 'publication_type', 'year'
).<b>annotate(
    total=Sum('counts')
)</b>.order_by(
    'title', 'publisher', 'doi', 'publication_type', 'year'
)

, в результате чего получается QuerySet словарей:

<QuerySet [
    {'title': 'Title A', 'publisher': 'pubA', ..., 'total': 11},
    {'title': 'Title B', 'publisher': 'pubA', ..., 'total': 7},
    {'title': 'Title A', 'publisher': 'pubB', ..., 'total': 3},
]>

Но, как вы можете видеть, запрос не дает моделей, и он немного "нестабилен" в том смысле, что каждый раз, когда вы добавляете дополнительные данные вашей "функционально связанной сущности", вам нужно будет обновить запрос.

0 голосов
/ 23 мая 2019

Замените ваш запрос на

self.model.objects.filter(q_report).annotate(total=Sum('counts')).values('title','total')

Где сумма будет поле, которое вы хотите суммировать

...