如果我们有两个模型A,B有一个多到多的关系。
我希望获得类似于以下内容的sql查询:
SELECT *
FROM a LEFT JOIN ab_relation
ON ab_relation.a_id = a.id
JOIN b ON ab_relation.b_id = b.id;所以在django当我尝试:
A.objects.prefetch_related('bees')我收到了两个类似于以下内容的查询:
SELECT * FROM a;
SELECT ab_relation.a_id AS prefetch_related_val_a_id, b.*
FROM b JOIN ab_relation ON b.id = ab_relation.b_id
WHERE ab_relation.a_id IN (123, 456... list of all a.id);考虑到A和B有中等大的表,我发现django的方式对于我的需要来说太慢了。
问题是:是否可以通过ORM获得左联接手动写入查询?
编辑以回答一些澄清:
LEFT OUTER JOIN会更好地获得查询集中的所有A,而不仅仅是那些与B(更新的sql)有关系的。Prefetch('bees', queryset=B.objects.values('one_field'))之后,一个错误告诉您不能在预取中使用values。发布于 2018-11-20 08:31:05
直接回答跳到第6点)
让我们一步一步地谈。
1) N:M选择。你说你想要这样的查询:
SELECT *
FROM a JOIN ab_relation ON ab_relation.a_id = a.id
JOIN b ON ab_relation.b_id = b.id;但这不是真正的N:M查询,因为您只获得与are相关的对象,查询应该使用outer joins。至少像:
SELECT *
FROM a left outer JOIN
ab_relation ON ab_relation.a_id = a.id left outer JOIN
b ON ab_relation.b_id = b.id;在其他情况下,您只获得带有相关B的B模型。
2) 阅读大表----你说的是“中等大的表”。那么,您确定要从数据库读取整个表吗?这在web环境中并不常见,可以读取大量数据,在这种情况下,您可以对数据进行分页。可能不是一个网络应用?你为什么要看这张大桌子?我们需要背景来回答你的问题。您确定需要两个表中的所有字段吗?
3) Select 您确定需要两个表中的所有字段吗?如果只读取某些值,则此查询将运行得更快。
A.objects.values( "some_a_field", "anoter_a_field", "Bs__some_b_field" )4) 作为总结。ORM是一个强大的工具,两个单一的读取操作都是“快速”的。我写了一些想法,但也许我们需要更多的上下文来回答你的问题。什么意味着中等大的表,小麦的意思是慢,您对这些数据做什么,每个表的每一行有多少字段或字节,.。
编辑了,因为OP编辑了这个问题。
5) 使用右UI控件。你说:
查询集将用作多选择表单字段的选项,在该字段中,我们需要表示与B有关系的A对象,该对象具有来自B.field的额外字符串。
它看起来像一个反模式发送到客户端4k行为一个表单。我建议您移到一个只加载所需数据的实时控件中。例如,通过某些文本进行过滤。看一看django-select2 2出色的项目。
6)你说
问题是:是否可以通过ORM获得左联接手动写入查询?
答案是:是,您可以使用values,正如我在第3点上说的那样。示例:Material和ResultatAprenentatge是N:M关系:
>>> print( Material
.objects
.values( "titol", "resultats_aprenentatge__codi" )
.query )查询:
SELECT "material_material"."titol",
"ufs_resultataprenentatge"."codi"
FROM "material_material"
LEFT OUTER JOIN "material_material_resultats_aprenentatge"
ON ( "material_material"."id" =
"material_material_resultats_aprenentatge"."material_id" )
LEFT OUTER JOIN "ufs_resultataprenentatge"
ON (
"material_material_resultats_aprenentatge"."resultataprenentatge_id" =
"ufs_resultataprenentatge"."id" )
ORDER BY "material_material"."data_edicio" DESC https://stackoverflow.com/questions/53388750
复制相似问题