假设我有一个与模型B具有一对多关系的模型A,它与模型C具有一对一的关系。模型C具有包含数值的属性X.这说明如下:
表达查询的最佳方式是什么?我想要模型A的所有实例,其相关模型C上的属性X(通过模型B)在它们之间有一定的百分比差异?
例如:
我想要所有相关模型C的X属性相差20%或更多的所有A:
MODELA [ID = 1]
型号Bs [A1:B1,A1:B2,A1:B3]
模型Cs attr x值[A1:B1:C:attrX => 10,A1:B2:C:attrX => 14,A1:B3:C:attrX => 13]
此示例符合条件,因为A1:B1:C:attrX与至少一个其他attrX的差异为20%或更高
编辑1:
如果其他查询不可行,我也会对按B或A分组的所有模型C感兴趣。
甚至所有模型B都按A ...
分组答案 0 :(得分:1)
我想要所有相关模型C的X属性有20%或更多差异的所有A
如果A的C.x中的任何一个具有%20的差异,那么该A的MAX和MIN C.x肯定具有至少%20或更大的差异。您可以根据该事实构建查询。使用aggregate expressions,您可以执行以下操作:
A.objects.annotate(
max_diff=(Max('b__c__x') - Min('b__c__x')) * 100 / Min('b__c__x')
).filter(max_diff__gte=20)
当然b,c代表外国或多对多关系的相关名称。这将首先注释具有max_diff
百分比的对象,然后我们过滤该值。根据您的字段类型,您可能还需要指定output_field。
我不知道您问题的具体细节,但我也建议您查看可用的aggregation functions,也许标准偏差或差异会有所帮助。
参考:
答案 1 :(得分:0)
这在orm中可能是可行的,但这听起来像是一堆乱七八糟的东西(需要确保那些在所有平均值的20%范围内的数量与数量相同)打电话给他们)。这似乎是一个预取的好机会。也许像是
for a in A.objects.prefetch_related("b_set__c"):
cs = [b.c for b in a.b_set.all()]
然后你可以在python中应用你的过滤,这将使它更可检查,并且应该只运行有限数量的查询。唯一的问题是,您的查询集可能不会太大而无法完全迭代此结果。
如果此方法效果不佳,可以通过添加列来指示这是否符合您的低变异性标准,并在保存B
和{{1 }}