【问题标题】:get ids group by range django按范围 django 获取 ids group
【发布时间】:2018-08-20 09:58:11
【问题描述】:

我有: 型号:

id = PrimaryKey()
value = IntegerField()

我想按1-7 和8-30 和>30 之间的值范围获取ID 组列表。
这样做的有效方法是什么?
或者我应该为每个范围编写查询,例如:

one= Model.objects.filter(value__gt=0,value__lte=7).values_list(id)
two= Model.objects.filter(value__gt=7,value__lte=30).values_list(id)
three= Model.objects.filter(value__gt=30).values_list(id)

... 我可以通过aggregate Count 这样做吗?我想要最少的数据库事务。

更新:

实际上我正在尝试获取销售了多少产品,如果它们很快到期,那么每周计数,否则每月计数:

  • 牛奶在 3 天后过期。过去 3 年卖出了多少牛奶包 天
  • 面包在 7 天后过期。过去 7 天卖出了多少面包。

这里value 是expires_in,即产品在多少天后到期
(expiry date - mfg date)

模型是这样的:

发票拆分

product_id
name
desctiption
expires_in

【问题讨论】:

  • 你需要数数还是ids?
  • @WillemVanOnsem 更新问题请参阅

标签: django django-queryset


【解决方案1】:

与groupby

如果您需要ids,我们可以使用itertools 的groupby:

from itertools import groupby
from operator import itemgetter

def rank(itm):
    vl = itm['value']
    if vl <= 7:
        return 0
    elif vl <= 30:
        return 1
    return 2

dat = {
    k: list(map(itemgetter('id'),v))
    for k, v in groupby(
        Model.objects.filter(value__gt=0).values('id', 'value').order_by('value'),
        rank)
}

现在dat 将包含三个元素:0 包含1-7、1 范围内的元素列表,因为8-30 和2 范围内的元素是ids价值 30+。

然后我们可以得到ids的列​​表,用:

dat[0]  # ids with value 1-7
dat[1]  # ids with value 8-30
dat[2]  # ids with value 31+

这将产生一个查询,我们让 Python 进行分组。如果数据量很大,这可能会很慢,但它已经变得很慢,因为元素的反序列化也需要相当的努力。

优化检查

我们可以让数据库执行确定类别的逻辑,从而将一些工作从 Python 转移到数据库:

from django.db.models import Case, IntegerField, Value

qs = Model.objects.filter(value__gt=0).annotate(
    cat = Case(
        When(value__lt=8, then=Value(0)),
        When(value__lt=31, then=Value(1)),
        default=Value(2),
        output_field=IntegerField(),
    ))
).values('id', 'cat').order_by('cat')

然后构造字典:

from operator import itemgetter
from itertools import groupby

data = {
    k: list(map(itemgetter('id'), v))
    for k, v in groupby(qs, itemgetter('cat'))
}

【讨论】:

  • 先生,我也可以算一下吗?如更新的问题部分所述。
  • 您可以调用列表中的len(..),如果您只对计数感兴趣,则可以更高效地完成查询。但如果你也对ids 感兴趣,那么最好“piggyback”对id 分类部分所做的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 2016-05-21
  • 2013-10-20
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多