简体   繁体   English

Django:根据条件选择查询集字段

[英]Django: Selecting queryset fields based on a condition

Folks, 民间,

Here's the schema of the table T (Let's say Model name is also T with fields A, B and C): 这是表T的架构(假设模型名称也是T,其中包含字段A,B和C):

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

Now, I want to select values (A, C or B). 现在,我要选择值(A,C或B)。 I can select A and C as follows: 我可以如下选择A和C:

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

But it will give me A and C values only. 但这只会给我A和C值。 All I want is if C is NULL, then I should get B. I don't know whether I can achieve this directly using any condition or join (Sorry, I'm not a SQL guy) but I can definitely achieve this using follows: 我只想如果C为NULL,那么我应该得到B。我不知道我是否可以使用任何条件或联接直接实现此功能(对不起,我不是SQL专家),但是我绝对可以使用以下方法实现此功能:

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

So, there are two open questions: 因此,有两个悬而未决的问题:

  1. Is there any better way of doing it? 有什么更好的方法吗? (Preferably using Queryset/Django ORM functions) (最好使用Queryset / Django ORM函数)

  2. In case of tens of thousands of records, what is the memory efficient / optimized way of doing this? 对于成千上万的记录,执行此操作的内存效率/优化方式是什么? Is there any way other than limiting the queryset into smaller chunks (let's say 1000 records at once) using the loop (assuming ordered primary key) as follows: 除了使用循环(假设有序的主键)将查询集限制为较小的块(假设一次有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 

In answer to your second question for very large data sets you may want to look at the iterator: 在回答有关非常大的数据集的第二个问题时,您可能需要查看迭代器:

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

As this won't try and load the entire data set at time of evaluation, but obviously there are trade offs. 因为这不会在评估时尝试加载整个数据集,但是显然存在一些折衷。

I think I can answer the first question. 我想我可以回答第一个问题。

1. Is there any better way of doing it? 1.有更好的方法吗? (Preferably using Queryset/Django ORM functions) (最好使用Queryset / Django ORM函数)

Django provides Conditional expressions that lets you do this. Django提供了条件表达式 ,您可以执行此操作。

From Django docs, 从Django文档中,

Conditional expressions let you use if … elif … else logic within filters, annotations, aggregations, and updates. 条件表达式使您可以使用if…elif…else过滤器,注释,聚合和更新中的逻辑。 A conditional expression evaluates a series of conditions for each row of a table and returns the matching result expression. 条件表达式为表的每一行评估一系列条件,并返回匹配的结果表达式。

For the schema you provided, you can use this: 对于您提供的模式,可以使用以下命令:

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

For every row, this selects the value in column B if the value in column C is null. 对于每一行,如果C列中的值为null,则选择B列中的值。 Otherwise, value in column C is selected. 否则,将选择C列中的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM