You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Django ORM实现子查询的技术求助

用Django ORM实现子查询:结合你的评分表实例

嘿,我明白你卡在Django ORM子查询这儿的感觉了——一开始确实有点绕,不过结合你给出的评分表结构,咱们一步步拆解,用实际场景的例子来搞懂它!

首先,先把你的数据表转换成对应的Django Model(这是ORM操作的基础):

from django.db import models
from django.contrib.auth.models import User

class Rating(models.Model):
    id = models.AutoField(primary_key=True)
    rating = models.CharField(max_length=1, null=False)
    product = models.ForeignKey('Product', on_delete=models.CASCADE, db_column='product_id', related_name='ratings')
    user = models.ForeignKey(User, on_delete=models.SET_NULL, db_column='user_id', null=True, related_name='ratings')
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = '你的评分表表名'  # 替换成你实际的表名

(假设你有对应的Product模型,基础版本如下)

class Product(models.Model):
    name = models.CharField(max_length=100)
    # 其他你需要的字段

接下来,咱们看几个最常用的子查询场景,每个场景都会对应SQL逻辑和Django ORM代码,帮你理解对应关系:

场景1:获取每个产品的最新评分

这是很常见的需求——你想知道每个产品最近一次被评分的记录。

对应的SQL逻辑大概是这样:

SELECT *
FROM rating r
WHERE r.created_at = (
    SELECT MAX(created_at)
    FROM rating
    WHERE product_id = r.product_id
);

用Django ORM实现的话,需要用到SubqueryOuterRef这两个工具:

from django.db.models import Subquery, OuterRef, Max

# 第一步:定义子查询——获取每个产品的最新创建时间
latest_rating_time = Rating.objects.filter(
    product_id=OuterRef('product_id')  # 用OuterRef引用外层查询的product_id
).values('product_id').annotate(
    latest_created=Max('created_at')
).values('latest_created')  # 只取出最新时间这个值

# 第二步:用子查询作为条件,筛选出对应评分记录
latest_ratings = Rating.objects.filter(
    created_at=Subquery(latest_rating_time)
)

这里的OuterRef就像是个“桥梁”,让内层的子查询能关联到外层查询的每条产品记录,Subquery则把内层查询的结果当作外层查询的筛选条件。

场景2:获取每个用户的最高评分

假设你的rating字段是按字符串排序的(比如'A'是最高,'E'是最低),想找出每个用户给出的最高评分记录。

对应的SQL:

SELECT *
FROM rating r
WHERE r.rating = (
    SELECT MAX(rating)
    FROM rating
    WHERE user_id = r.user_id
);

ORM实现:

from django.db.models import Subquery, OuterRef, Max

# 子查询:获取每个用户的最高评分值
user_max_rating = Rating.objects.filter(
    user_id=OuterRef('user_id')
).values('user_id').annotate(
    max_rating=Max('rating')
).values('max_rating')

# 筛选出每个用户对应最高评分的记录
user_top_ratings = Rating.objects.filter(
    rating=Subquery(user_max_rating)
)

场景3:筛选出有评分的产品(存在性检查)

如果你想找出所有至少被评过分的产品,用Exists子查询会比传统的__exists更灵活(还能扩展额外条件)。

ORM代码:

from django.db.models import Exists, OuterRef

# 筛选所有有评分的产品
rated_products = Product.objects.filter(
    Exists(Rating.objects.filter(product_id=OuterRef('id')))
)

# 扩展:筛选出被特定用户(比如id=1)评过分的产品
user_rated_products = Product.objects.filter(
    Exists(Rating.objects.filter(product_id=OuterRef('id'), user_id=1))
)

Exists会检查每条产品记录是否满足子查询的条件,它的执行效率通常比count()或者__in更高,因为只要找到匹配的记录就会停止查询。

核心知识点总结

  • Subquery:用来将一个查询的结果作为另一个查询的条件,通常返回单个值或一列值
  • OuterRef:用来引用外层查询中的字段,实现内外层查询的关联
  • Exists:专门用于存在性检查的子查询,高效且灵活

如果还有特定的子查询需求,比如更复杂的关联或者聚合,随时补充细节就行!

内容的提问来源于stack exchange,提问作者Why

火山引擎 最新活动