如何在使用 distinct 后执行 order_by?
How to execute an order_by after using distinct?
我想在基于两个字段抓取唯一结果后对结果进行排序。我遇到的问题是我不能在 Django 中使用两个 order_by。 Django clears the previous order_by()
whenever you use this function.
Each order_by() call will clear any previous ordering.
模型示例:
class Product(models.Model):
price = models.FloatField()
name = models.CharField(max_length=100)
group = models.CharField(max_length=100)
我想得到同组最低价的商品。然后,我想按价格对它们进行排序。像这样:
Product.objects.order_by('group','price').distinct('group').order_by('price')
Product.objects.order_by('group','price').distinct('group').order_by('-price')
问题是,如果只是在第一个订单中使用,我会得到不同的产品。
--
编辑
table的例子:
id | name | group | price
0 | aaa | aaa | 10.0
1 | aaa | aaa | 1.0
2 | aaa | aaa | 2.0
3 | aaa | aaa | 1.0
4 | bbb | bbb | 2.0
5 | bbb | bbb | 2.1
6 | bbb | bbb | 10.0
按价格排序:
1 | aaa | aaa | 1.0
4 | bbb | bbb | 2.0
按价格排序:
4 | bbb | bbb | 2.0
1 | aaa | aaa | 1.0
我遇到的问题是,当我使用 order_by 排序时,返回的产品不同。
在 sql 语句中是这样的:
SELECT *
FROM product
WHERE id IN (
SELECT DISTINCT ON
(group) id
FROM product
ORDER BY group ASC, price ASC
)
ORDER BY price DESC
我正在使用 PostgreSQL
好的,这是我所做的:
products = Product.objects.order_by('group','price').distinct('group')
result = Product.objects.filter(id__in=products).order_by('-price')
我认为这不是最有效的方法,但它确实有效...
我遇到了同样的问题并找到了另一个解决方案。在第一次使用 sorted_by 后跟 distinct 请求 DB 后,您可以:
import operator
products = Product.objects.order_by('group','price').distinct('group')
result = sorted(products, key=operator.attrgetter('price'), reverse=True)
这个解决方案更好,因为您没有向数据库发出第二个请求。
我喜欢亚历山大使用排序的想法。我将排序后的函数放入 models.QuerySet 的子类中,然后相应地设置我的 ProductManager。这允许您将排序方法链接到您的查询集。
陷阱:这个returns一个列表而不是一个查询集,所以你不能在排序后使用任何查询集方法。
相关模型字段排序:您可以通过使用点运算符传递跨越查找的键来按相关模型字段排序(key='price.other')
manager.py
class ProductQuerySet(models.QuerySet):
def sorted(self, key, reverse=False):
""" Returns a list (rather than queryset) of Djano model instances """
return sorted(self, key=operator.attrgetter(key), reverse=reverse)
def current(self):
return self.order_by('group', 'price').distinct('group')
class ProductManagerBase(models.Manager):
pass
ProductManager = ProductManagerBase.from_queryset(ProductQuerySet)
models.py
...
objects = ProductManager()
**查询
qs = (Product
.current()
.sorted('price', reverse=True))
我想在基于两个字段抓取唯一结果后对结果进行排序。我遇到的问题是我不能在 Django 中使用两个 order_by。 Django clears the previous order_by()
whenever you use this function.
Each order_by() call will clear any previous ordering.
模型示例:
class Product(models.Model):
price = models.FloatField()
name = models.CharField(max_length=100)
group = models.CharField(max_length=100)
我想得到同组最低价的商品。然后,我想按价格对它们进行排序。像这样:
Product.objects.order_by('group','price').distinct('group').order_by('price')
Product.objects.order_by('group','price').distinct('group').order_by('-price')
问题是,如果只是在第一个订单中使用,我会得到不同的产品。
--
编辑
table的例子:
id | name | group | price
0 | aaa | aaa | 10.0
1 | aaa | aaa | 1.0
2 | aaa | aaa | 2.0
3 | aaa | aaa | 1.0
4 | bbb | bbb | 2.0
5 | bbb | bbb | 2.1
6 | bbb | bbb | 10.0
按价格排序:
1 | aaa | aaa | 1.0
4 | bbb | bbb | 2.0
按价格排序:
4 | bbb | bbb | 2.0
1 | aaa | aaa | 1.0
我遇到的问题是,当我使用 order_by 排序时,返回的产品不同。
在 sql 语句中是这样的:
SELECT *
FROM product
WHERE id IN (
SELECT DISTINCT ON
(group) id
FROM product
ORDER BY group ASC, price ASC
)
ORDER BY price DESC
我正在使用 PostgreSQL
好的,这是我所做的:
products = Product.objects.order_by('group','price').distinct('group')
result = Product.objects.filter(id__in=products).order_by('-price')
我认为这不是最有效的方法,但它确实有效...
我遇到了同样的问题并找到了另一个解决方案。在第一次使用 sorted_by 后跟 distinct 请求 DB 后,您可以:
import operator
products = Product.objects.order_by('group','price').distinct('group')
result = sorted(products, key=operator.attrgetter('price'), reverse=True)
这个解决方案更好,因为您没有向数据库发出第二个请求。
我喜欢亚历山大使用排序的想法。我将排序后的函数放入 models.QuerySet 的子类中,然后相应地设置我的 ProductManager。这允许您将排序方法链接到您的查询集。
陷阱:这个returns一个列表而不是一个查询集,所以你不能在排序后使用任何查询集方法。
相关模型字段排序:您可以通过使用点运算符传递跨越查找的键来按相关模型字段排序(key='price.other')
manager.py
class ProductQuerySet(models.QuerySet):
def sorted(self, key, reverse=False):
""" Returns a list (rather than queryset) of Djano model instances """
return sorted(self, key=operator.attrgetter(key), reverse=reverse)
def current(self):
return self.order_by('group', 'price').distinct('group')
class ProductManagerBase(models.Manager):
pass
ProductManager = ProductManagerBase.from_queryset(ProductQuerySet)
models.py
...
objects = ProductManager()
**查询
qs = (Product
.current()
.sorted('price', reverse=True))