Как я могу отсортировать по DateTimeField и выбрать отдельные элементы на основе ForeignKey? - PullRequest
0 голосов
/ 29 сентября 2018

Я использую PostgreSQL в качестве базы данных для моего проекта Django.У меня есть следующие модели:

class Food(models.Model):
    """Stores a food entry"""
    name = models.CharField(max_length=50)
    image_id = models.CharField(max_length=20)
    description = models.TextField()

class SurveyResult(models.Model):
    """Stores survey food result based on emoji and personality"""
    emoji = models.CharField(max_length=10)
    personality = models.CharField(max_length=50)
    food = models.ForeignKey(Food, on_delete=models.CASCADE)
    timestamp = models.DateTimeField(auto_now_add=True)
    rating = models.PositiveSmallIntegerField(default=0)

Мне нужно написать запрос, отсортированный по '-timestamp', и просто получить различные значения для 'food'.Это то, что я пробовал:

SurveyResult.objects.order_by('-timestamp').distinct('food')

Однако я получаю следующую ошибку:

ProgrammingError: Выражения SELECT DISTINCT ON должны соответствовать исходным выражениям ORDER BY LINE 1:ВЫБЕРИТЕ DISTINCT ON ("Recommender_surveyresult". "Food_id") "r ...

Я прочитал несколько ответов на несколько вопросов, и я нашел ответ, который в основном говорит сделать что-то вроде этого:

SurveyResult.objects.order_by('food', '-timestamp').distinct('food')

Тем не менее, я не получаю то, что мне нужно, это последние SurveyResult объекты, которые имеют различный food.

Как мне этого достичь?

Предположим, у меня есть следующая таблица в моей базе данных:

# surveyresults
id emoji personality food timestamp            rating
1  :)    Famous US     1  2018-01-01 - 9:00      1
2  XD    Famous CN     3  2018-01-01 - 9:10      2
3  :)    Famous NZ     5  2018-01-01 - 9:15      3
4  :(    Famous FR     5  2018-01-01 - 9:35      4
5  XD    Famous US     1  2018-01-01 - 9:45      5
6  ;)    Famous JP     4  2018-01-01 - 9:55      5
7  :o    Famous SP     4  2018-01-01 - 10:00     5

Запрос должен дать мне следующее:

id emoji personality food timestamp            rating
7  :o    Famous SP     4  2018-01-01 - 10:00     5
5  XD    Famous US     1  2018-01-01 - 9:45      5
4  :(    Famous FR     5  2018-01-01 - 9:35      4
2  XD    Famous CN     3  2018-01-01 - 9:10      2

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

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Вы можете рассмотреть возможность добавления метакласса в модель SurveyResults, а затем указать там свой заказ

class SurveyResult(models.Model):
    ...

   class Meta:
        ordering = ('-timestamp',)
0 голосов
/ 29 сентября 2018

Вы можете достичь этого, используя subquery, как показано ниже,

SurveyResult.objects.filter(
    id__in=SurveyResult.objects.order_by('food', '-timestamp').distinct('food')
).order_by('-timestamp')

Объяснение:

Таким образом, в основном subquery предполагает оценку более чем одного query в вашем случае мы оцениваем два запроса.SQL для вышеприведенного queryset будет выглядеть так:

SELECT "id", "emoji", "personality", "food", "timestamp", "rating"
FROM "appname_surveyresult"
WHERE id IN (
    SELECT "id", DISTINCT ON ("food") 
    FROM "appname_surveyresult"
    ORDER BY "food" ASC, "timestamp" DESC 
)
ORDER BY "timestamp" DESC

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...