让我们一起走向未来
🎓作者简介:全栈领域优质创作者
🌐个人主页:百锦再@新空间代码工作室
💡座右铭:坚持自己的坚持,不要迷失自己!要快乐
目录
- 让我们一起走向未来
- Django中ORM实现对检索集合排序,去重,分组,子查询
- 1. 排序(Ordering)
- 示例:按字段升序排序
- 示例:按字段降序排序
- 示例:按多个字段排序
- 2. 去重(Distinct)
- 示例:去重
- 示例:去重并返回所有字段
- 注意:使用 `distinct()` 时,可能需要对查询的字段进行分组或限制字段。
- 3. 分组(Grouping)
- 示例:按作者分组并统计每个作者的图书数量
- 示例:按作者分组并计算每个作者的图书总价
- 4. 子查询(Subqueries)
- 示例:使用子查询获取每个作者的最新出版图书
- 示例:用子查询获取每本图书的最大评论数(假设 `Book` 和 `Review` 关联)
- 5. 结合多个操作
- 示例:按作者分组,获取每个作者的图书总数,并按图书总数降序排序
- 示例:获取每个作者的图书总价格,并按价格降序排序
- 6. 排除某些字段(Exclude)
- 总结
Django中ORM实现对检索集合排序,去重,分组,子查询
在Django ORM中,除了常规的CRUD操作外,还可以进行复杂的查询操作,例如对检索集合进行排序、去重、分组以及执行子查询等。下面详细介绍如何实现这些操作。
1. 排序(Ordering)
Django ORM 提供了 order_by()
方法来进行排序。你可以按一个或多个字段进行升序或降序排序。
示例:按字段升序排序
# 按价格升序排序
books = Book.objects.all().order_by('price')
示例:按字段降序排序
# 按价格降序排序
books = Book.objects.all().order_by('-price')
示例:按多个字段排序
# 先按作者名字升序排序,再按价格降序排序
books = Book.objects.all().order_by('author', '-price')
2. 去重(Distinct)
Django ORM 提供了 distinct()
方法来去重,返回唯一的结果集。distinct()
只会去除整个字段集相同的记录。如果只去除某个字段的重复值,可以结合 values()
使用。
示例:去重
# 获取所有独特的作者
authors = Book.objects.values('author').distinct()
示例:去重并返回所有字段
# 获取所有独特的图书
books = Book.objects.distinct()
注意:使用 distinct()
时,可能需要对查询的字段进行分组或限制字段。
3. 分组(Grouping)
Django ORM 提供了 annotate()
方法结合聚合函数来实现分组查询。常见的聚合函数有:Count
、Sum
、Avg
、Max
、Min
等。你可以根据某个字段进行分组,并对其他字段进行计算。
示例:按作者分组并统计每个作者的图书数量
from django.db.models import Count
# 按作者分组,统计每个作者的图书数量
authors_count = Book.objects.values('author').annotate(num_books=Count('id')).order_by('-num_books')
for author in authors_count:
print(f"作者:{author['author']}, 图书数量:{author['num_books']}")
示例:按作者分组并计算每个作者的图书总价
from django.db.models import Sum
# 按作者分组,计算每个作者的图书总价
authors_sum = Book.objects.values('author').annotate(total_price=Sum('price')).order_by('-total_price')
for author in authors_sum:
print(f"作者:{author['author']}, 总价:{author['total_price']}")
4. 子查询(Subqueries)
Django ORM 提供了支持子查询的功能。你可以通过 Subquery
和 OuterRef
实现对子查询结果的引用。
示例:使用子查询获取每个作者的最新出版图书
假设你有两个模型:Book
和 Author
,我们想要获取每个作者的最新出版图书。
from django.db.models import OuterRef, Subquery
# 获取每个作者的最新出版图书标题
latest_book = Book.objects.filter(author=OuterRef('pk')).order_by('-published_date')
# 使用子查询
authors = Author.objects.annotate(latest_book_title=Subquery(latest_book.values('title')[:1]))
for author in authors:
print(f"作者:{author.name}, 最新图书:{author.latest_book_title}")
在这个例子中,我们使用 Subquery
来获取每个作者的最新出版图书。OuterRef('pk')
表示外部查询(Author
模型)中的主键,Subquery
将会替换为子查询返回的结果。
示例:用子查询获取每本图书的最大评论数(假设 Book
和 Review
关联)
from django.db.models import Count, OuterRef, Subquery
# 假设每本图书有多个评论
reviews_count = Review.objects.filter(book=OuterRef('pk')).values('book').annotate(num_reviews=Count('id'))
# 使用子查询获取每本图书的评论数
books = Book.objects.annotate(num_reviews=Subquery(reviews_count.values('num_reviews')[:1]))
for book in books:
print(f"书名:{book.title}, 评论数:{book.num_reviews}")
5. 结合多个操作
你可以将排序、去重、分组等操作结合使用,以满足更复杂的查询需求。
示例:按作者分组,获取每个作者的图书总数,并按图书总数降序排序
from django.db.models import Count
# 按作者分组,计算每个作者的图书数量,并按数量降序排序
authors_books_count = Book.objects.values('author') \
.annotate(num_books=Count('id')) \
.order_by('-num_books')
for author in authors_books_count:
print(f"作者:{author['author']}, 图书数量:{author['num_books']}")
示例:获取每个作者的图书总价格,并按价格降序排序
from django.db.models import Sum
# 按作者分组,计算每个作者的图书总价格,并按总价降序排序
authors_books_value = Book.objects.values('author') \
.annotate(total_price=Sum('price')) \
.order_by('-total_price')
for author in authors_books_value:
print(f"作者:{author['author']}, 总价格:{author['total_price']}")
6. 排除某些字段(Exclude)
有时你可能需要排除某些数据或字段,可以通过 exclude()
方法来实现。
# 排除价格大于50的图书
books = Book.objects.exclude(price__gt=50)
总结
Django ORM 提供了强大的查询功能,包括排序、去重、分组和子查询等常见操作。通过合理使用 order_by()
、distinct()
、annotate()
、Subquery
和其他查询方法,你可以实现复杂的数据库操作,而无需编写原生SQL。合理组合这些功能,可以帮助你高效地实现业务逻辑中的复杂查询需求。