#sql #django
Есть две модели - Покупатель и Заказ: class Customer(AbstractUser): pass class Order(models.Model): SHOP_1, SHOP_2, SHOP_3 = 1, 2, 3 SHOP_CHOICES = ( (SHOP_1, 'Shop 1'), (SHOP_2, 'Shop 2'), (SHOP_3, 'Shop 3'), ) customer = models.ForeignKey(Order, related_name='orders') shop = models.IntegerField(choices=SHOP_CHOICES) updated_dt = models.DateTimeField(auto_now=True) price = models.DecimalField() Надо по каждому пользователю вывести последние заказы по каждому магазину. То есть из этого: Customer +-----+----------+ | id | username | +-----+----------+ | 1 | Garry | | ... | ... | +-----+----------+ Order +-----+-------------+------+---------------------+-------+ | id | customer_id | shop | updated_dt | price | +-----+-------------+------+---------------------+-------+ | 1 | 1 | 1 | 2017-07-01 00:00:00 | 12 | | 2 | 1 | 1 | 2017-07-02 00:00:00 | 23 | | 3 | 1 | 2 | 2017-07-01 00:00:00 | 35 | | 4 | 1 | 2 | 2017-07-02 00:00:00 | 23 | | 5 | 1 | 2 | 2017-07-03 00:00:00 | 93 | | 6 | 1 | 3 | 2017-07-04 00:00:00 | 230 | | ... | ... | ... | ... | ... | +-----+-------------+------+---------------------+-------+ Надо получить это: +-----+-------------+------+---------------------+-------+ | id | customer_id | shop | updated_dt | price | +-----+-------------+------+---------------------+-------+ | 2 | 1 | 1 | 2017-07-02 00:00:00 | 23 | | 5 | 1 | 2 | 2017-07-03 00:00:00 | 93 | | 6 | 1 | 3 | 2017-07-04 00:00:00 | 230 | +-----+-------------+------+---------------------+-------+ Есть идея реализовать данный вывод через join таблицы заказов к этой же таблице: SELECT order1.* FROM order order1 LEFT JOIN order order2 ON (order1.shop = order2.shop AND order1.updated_dt < order2.updated_dt AND order1.customer_id = order2.customer_id) WHERE stat2.id IS NULL AND stat1.customer_id = 1; Но, насколько я понимаю, в Django нельзя явно join'ить таблицы.
Ответы
Ответ 1
Несколько лет не аботал с django. Раньше это делалось так: class Order(models.Model): SHOP_1, SHOP_2, SHOP_3 = 1, 2, 3 SHOP_CHOICES = ( (SHOP_1, 'Shop 1'), (SHOP_2, 'Shop 2'), (SHOP_3, 'Shop 3'), ) customer = models.ForeignKey('Order', related_name='orders') shop = models.IntegerField(choices=SHOP_CHOICES) updated_dt = models.DateTimeField(auto_now=True)Ответ 2
Есть наивный вариант: Order .object .filter(customer__id=1) .values("shop") .annotate( id=Max("id"), customer_id=Max("customer_id"), updated_dt=Max("updated_dt") ) В данном случае мы сначала делаем группировку по магазину, а далее выбираем максимальную дату и оборачиваем все остальные колонки в аггрегирующие функции. Работа с аггрегированием описанна в документации: https://docs.djangoproject.com/en/dev/topics/db/aggregation/#order-of-annotate-and-values-clauses If the values() clause precedes the annotate(), the annotation will be computed using the grouping described by the values() clause. However, if the annotate() clause precedes the values() clause, the annotations will be generated over the entire query set. In this case, the values() clause only constrains the fields that are generated on output.
Комментариев нет:
Отправить комментарий