Django запрос на удаление старых значений, сгруппированных по id? - PullRequest
0 голосов
/ 09 апреля 2020

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

примеры данных:

id     value    timestamp
10     10       9/4/20 17:00
11     17       9/4/20 17:00
21     50       9/4/20 17:00
10     10       9/4/20 16:00
10     10       9/4/20 15:00
10     11       9/4/20 14:00
11     41       9/4/20 16:00
11     41       9/4/20 15:00
21     50       9/4/20 16:00

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

id     value    timestamp
10     10       9/4/20 17:00
11     17       9/4/20 17:00
21     50       9/4/20 17:00
10     11       9/4/20 14:00
11     41       9/4/20 16:00

РЕДАКТИРОВАТЬ:

запрос просто

SampleData.objects.all()

1 Ответ

1 голос
/ 09 апреля 2020

Одним из подходов может быть использование Subquery выражений, как задокументировано здесь .

Предположим, ваша модель SampleData выглядит следующим образом:

class SampleData(models.Model):

    id2 = models.IntegerField()
    value = models.IntegerField()
    timestamp = models.DateTimeField()

(я заменил id на id2, чтобы избежать конфликтов с идентификатором модели).

Затем вы можете удалить свои дубликаты следующим образом:

newest = SampleData.objects.filter(id2=OuterRef('id2'), value=OuterRef('value')).order_by('-timestamp')
SampleData.objects.annotate(newest_id=Subquery(newest.values('pk')[:1])).exclude(pk=F('newest_id')).delete()

Редактировать:

Кажется, что MySQL имеет некоторые проблемы, связанные с удалением и подзапросами, как описано в этом SO сообщении.

В этом случае должен помочь двухэтапный подход: сначала получить идентификаторы удаляемых объектов, а затем удалить их:

 newest = SampleData.objects.filter(id2=OuterRef('id2'), value=OuterRef('value')).order_by('-timestamp')
 ids2delete = list(SampleData.objects.annotate(newest_id=Subquery(newest.values('pk')[:1])).exclude(pk=F('newest_id')).values_list('pk', flat=True))
 SampleData.objects.filter(pk__in=ids2delete).delete()
...