You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django ORM计算多时间段内指定品牌的市场份额?

解决方案:使用Django ORM计算品牌市场份额

方案一:使用CTE实现高效关联查询(推荐,需Django 3.2+)

该方案生成的SQL逻辑与你期望的一致,利用CTE替代子查询实现高效关联,同时保留ORM动态添加过滤条件的灵活性。

from django.db.models import Sum, F
from django.db.models.functions import Coalesce

# 创建CTE,计算每个时间段的全品牌总销售额
market_total_cte = MarketData.objects.values('time_period')\
    .annotate(market_total=Sum('sales'))\
    .with_cte('market_totals')

# 定义过滤条件(可动态添加更多WHERE子句)
filtered_data = MarketData.objects.filter(
    brand__in=['Brand 1', 'Brand 2'],
    time_period__range=('2020-01-01', '2023-03-31')
    # 示例:添加品类过滤 -> category='Electronics'
)

# 关联CTE并计算市场份额
result = market_total_cte.join(
    filtered_data,
    time_period=F('market_totals__time_period')
).values(
    'time_period', 'brand', 'market_totals__market_total'
).annotate(
    brand_sales=Sum('sales')
).annotate(
    # 使用Coalesce避免除以0的异常
    share=Coalesce(F('brand_sales') / F('market_totals__market_total'), 0.0)
).order_by('brand', 'time_period')

方案二:优化后的Subquery方案(兼容旧版Django)

若无法升级Django版本,可使用该方案,配合索引优化后性能可接近CTE方案。

from django.db.models import Sum, Subquery, OuterRef, F, IntegerField
from django.db.models.functions import Coalesce

# 子查询获取每个时间段的全品牌总销售额(限制返回单条结果)
total_sales_subquery = MarketData.objects.filter(
    time_period=OuterRef('time_period')
).values('time_period').annotate(
    total=Sum('sales')
).values('total')[:1]

# 主查询
result = MarketData.objects.filter(
    brand__in=['Brand 1', 'Brand 2'],
    time_period__range=('2020-01-01', '2023-03-31')
).values('time_period', 'brand').annotate(
    brand_sales=Sum('sales'),
    market_total=Subquery(total_sales_subquery, output_field=IntegerField())
).annotate(
    share=Coalesce(F('brand_sales') / F('market_total'), 0.0)
).order_by('brand', 'time_period')

性能优化建议

为大幅提升查询速度,需在MarketData模型中添加索引:

class MarketData(models.Model):
    category = models.CharField(max_length=64, null=True)
    brand = models.CharField(max_length=128, null=True)
    time_period = models.DateField(db_index=True)
    sales = models.IntegerField(default=0, null=True)

    class Meta:
        indexes = [
            # 优化时间段分组查询
            models.Index(fields=['time_period']),
            # 优化品牌+时间段的过滤与分组
            models.Index(fields=['brand', 'time_period']),
        ]

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:07:52