Django学习第三天:去重,分组,子查询_django

让我们一起走向未来

🎓作者简介:全栈领域优质创作者
🌐个人主页:百锦再@新空间代码工作室
💡座右铭:坚持自己的坚持,不要迷失自己!要快乐



目录

  • 让我们一起走向未来
  • Django中ORM实现对检索集合排序,去重,分组,子查询
  • 1. 排序(Ordering)
  • 示例:按字段升序排序
  • 示例:按字段降序排序
  • 示例:按多个字段排序
  • 2. 去重(Distinct)
  • 示例:去重
  • 示例:去重并返回所有字段
  • 注意:使用 `distinct()` 时,可能需要对查询的字段进行分组或限制字段。
  • 3. 分组(Grouping)
  • 示例:按作者分组并统计每个作者的图书数量
  • 示例:按作者分组并计算每个作者的图书总价
  • 4. 子查询(Subqueries)
  • 示例:使用子查询获取每个作者的最新出版图书
  • 示例:用子查询获取每本图书的最大评论数(假设 `Book` 和 `Review` 关联)
  • 5. 结合多个操作
  • 示例:按作者分组,获取每个作者的图书总数,并按图书总数降序排序
  • 示例:获取每个作者的图书总价格,并按价格降序排序
  • 6. 排除某些字段(Exclude)
  • 总结


Django学习第三天:去重,分组,子查询_子查询_02

Django中ORM实现对检索集合排序,去重,分组,子查询

在Django ORM中,除了常规的CRUD操作外,还可以进行复杂的查询操作,例如对检索集合进行排序、去重、分组以及执行子查询等。下面详细介绍如何实现这些操作。

Django学习第三天:去重,分组,子查询_字段_03

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')

Django学习第三天:去重,分组,子查询_数据库_04

2. 去重(Distinct)

Django ORM 提供了 distinct() 方法来去重,返回唯一的结果集。distinct() 只会去除整个字段集相同的记录。如果只去除某个字段的重复值,可以结合 values() 使用。

示例:去重
# 获取所有独特的作者
authors = Book.objects.values('author').distinct()
示例:去重并返回所有字段
# 获取所有独特的图书
books = Book.objects.distinct()
注意:使用 distinct() 时,可能需要对查询的字段进行分组或限制字段。

Django学习第三天:去重,分组,子查询_子查询_05

3. 分组(Grouping)

Django ORM 提供了 annotate() 方法结合聚合函数来实现分组查询。常见的聚合函数有:CountSumAvgMaxMin 等。你可以根据某个字段进行分组,并对其他字段进行计算。

示例:按作者分组并统计每个作者的图书数量
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学习第三天:去重,分组,子查询_字段_06

Django ORM 提供了支持子查询的功能。你可以通过 SubqueryOuterRef 实现对子查询结果的引用。

示例:使用子查询获取每个作者的最新出版图书

假设你有两个模型:BookAuthor,我们想要获取每个作者的最新出版图书。

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 将会替换为子查询返回的结果。

示例:用子查询获取每本图书的最大评论数(假设 BookReview 关联)

Django学习第三天:去重,分组,子查询_数据库_07

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学习第三天:去重,分组,子查询_django_08

总结

Django ORM 提供了强大的查询功能,包括排序、去重、分组和子查询等常见操作。通过合理使用 order_by()distinct()annotate()Subquery 和其他查询方法,你可以实现复杂的数据库操作,而无需编写原生SQL。合理组合这些功能,可以帮助你高效地实现业务逻辑中的复杂查询需求。