【问题标题】:Django: Selecting queryset fields based on a conditionDjango:根据条件选择查询集字段
【发布时间】:2013-10-23 21:38:11
【问题描述】:

伙计们,

这是表 T 的架构(假设模型名称也是 T,具有字段 A、B 和 C):

 A    B   C
---  --- ---
 1    a   b
 2    b   NULL
 3    c   c

现在,我想选择值(A、C 或 B)。我可以选择 A 和 C,如下所示:

 T.objects.all().values_list('A','C')

但它只会给我 A 和 C 值。我想要的只是如果 C 为 NULL,那么我应该得到 B。我不知道我是否可以直接使用任何条件或连接来实现这一点(对不起,我不是 SQL 人)但我绝对可以使用以下方法实现这一点:

 [(x,z or y) for (x,y,z) in T.objects.all().values_list('A','B','C')]

所以,有两个悬而未决的问题:

  1. 有没有更好的方法? (最好使用Queryset/Django ORM函数)

  2. 在成千上万条记录的情况下,这样做的内存高效/优化方式是什么?除了使用循环(假设是有序主键)将查询集限制为更小的块(假设一次 1000 条记录)之外,还有其他方法吗:

    max_pkey = T.objects.all().order_by('-pk')[0]
    current = 0
    chunk = 1000
    while current <= max_pkey:
        objs = T.objects.filter(pk__gt=current)[:chunk]
        Process the objects
    

【问题讨论】:

    标签: python sql django django-queryset


    【解决方案1】:

    我想我可以回答第一个问题。

    1.有没有更好的方法呢? (最好使用 Queryset/Django ORM 函数)

    Django 提供了Conditional expressions,让你可以做到这一点。

    来自 Django 文档,

    条件表达式允许您在过滤器、注释、聚合和更新中使用 if ... elif ... else 逻辑。条件表达式为表的每一行计算一系列条件并返回匹配的结果表达式。

    对于您提供的架构,您可以使用:

    T.objects.annotate(colA = F('A'), 
                       colB_C = Case(When(C__isnull=True, then=F('B')),
                                     default=F('C')))
    

    对于每一行,如果 C 列中的值为空,则选择 B 列中的值。否则,选择 C ​​列中的值。

    【讨论】:

      【解决方案2】:

      对于非常大的数据集,您可能需要查看迭代器的第二个问题:

      https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.iterator

      因为这不会在评估时尝试加载整个数据集,但显然需要权衡取舍。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-09
        • 2016-01-23
        • 2014-02-21
        • 1970-01-01
        • 2021-12-19
        • 2021-03-23
        • 2023-03-09
        • 2018-06-02
        相关资源
        最近更新 更多