как сгруппировать по столбцу и выбрать один объект, упорядоченный по времени создания - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть модель, подобная приведенной ниже,

class MusicData(BaseModel):
    name = models.CharField(max_length=100)
    url = models.URLField()
    description = models.TextField()
    age = models.CharField(max_length=25)
    language = models.ForeignKey(Language, on_delete=models.CASCADE, 
                                      related_name="music_data",
                                      related_query_name="music_data")
    count = models.IntegerField()
    last_updated = models.CharField(max_length=255)
    playlist = models.ForeignKey(PlayList, on_delete=models.CASCADE, 
                                      related_name="music_data",
                                      related_query_name="music_data")

Я хочу получить MusicData такой, что группа по имени, в каждой группе получит ту, которая имеет самую последнюю created_on (created_on являетсяDateTimeField in BaseModel)

предположим, что у меня есть следующие данные

| Name        | Created On            |
| ----------- | -----------           |
| ABC         | 2019-02-22 1:06:45 AM |
| ABC         | 2019-02-22 1:07:45 AM |
| BAC         | 2019-02-22 1:08:45 AM |
| BAC         | 2019-02-22 1:09:45 AM |
| BAC         | 2019-02-22 1:10:45 AM |
| BBC         | 2019-02-22 1:11:45 AM |

Ожидаемый результат:

| Name        | Created On            |
| ----------- | -----------           |
| ABC         | 2019-02-22 1:07:45 AM |
| BAC         | 2019-02-22 1:10:45 AM |
| BBC         | 2019-02-22 1:11:45 AM |

Я написал этот запрос, которыйотлично работает для описанного выше случая

models.MusicData.objects.filter(playlist__isnull=True).values(
        "name").annotate(maxdate=Max("created_on"))

Но проблема заключается в name и created_on Мне также нужны другие значения, такие как name, url, age, count, playlist__name и т.д ...

, поэтому я следовал этому руководству: https://docs.djangoproject.com/en/2.1/topics/db/aggregation/#combining-multiple-aggregations

Придумал этот запрос,

models.MusicData.objects.filter(playlist__isnull = True).values(
  "name").annotate(maxdate = Max("created_on")).values("age",
  "name",
  "description",
  "url",
  "count",
  "last_updated",
  "playlist",
  language = F(
    "language__name")
)

Но, в этом случаеЯ получил дубликаты объектов, затем я проверил SQL-запросы, я выяснил это

В первом случае только GROUP BY name есть вместе с соединениями, что хорошо

Но во втором случае,GROUP BY имеет все столбцы, которые я указал в значениях, я понимаю, что если мы хотим, чтобы столбец SELECT, мы должны включить в GROUP BY предложение

Я даже попытался создать списокid s затем фильтруют его, но в том же случае он агрегирует по всему набору запросов

result = models.MusicData.objects.filter(playlist__isnull=True).values(
        "name").annotate(maxdate=Max("created_on")).values_list("id", flat=True)
# Then filter on this list of id's

Кто-нибудь мне поможет ???

Примечание: я использую PostgreSQLбазы данных

1 Ответ

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

Наконец-то разобрался, я мог бы сделать это в PostgreSQL

MusicData.objects.order_by('name', '-created_on').distinct('name')..values(
            "age",
            "name",
            "description",
            "url",
            "since_last_pushed",
            "last_updated",
            language=F("language__name"),
        )

, что приведет меня к следующему запросу:

SELECT DISTINCT ON ('name', 'created_on')
  id,
  name,
  url,
  description,
  ... etc,
FROM
  musicdata
ORDER BY name ASC,
         created_on DESC;

Интересно, это тяжело?вопрос, который был более 2 дней, но не получил никакого ответа здесь, удивляет меня, я ожидал ответа в часах, я ошибся темами ???

...