我在MySQL中使用Django ORM,在querys中浪费了很多时间。对于一些“高级”情况,我决定使用原始查询,因为对于那些情况,我不能使用注释。原始查询的问题是没有像注释或聚合那样向queryset添加“字段”。所以,我用的是额外的。但现在我面临一个问题:

qs_products = Productos.objects.all()
qs_productos.extra({
    "stock":
    """
        SELECT SUM(items.cantidad)
        FROM
            `encargosProveedor_listado_articulos` AS encargos,
            `itemArticulosProveedor`AS items, `articulos` as articulos
        WHERE
            encargos.itemarticulosproveedor_id=items.id and
            articulos.id=items.articulos_id
        GROUP BY articulos.producto_id
    """
    })

这是直接从我的数据库管理员查询的结果:
+---------------------+
| SUM(items.cantidad) |
+---------------------+
|          14         |
+---------------------+
|          4          |
+---------------------+

但是当在django下使用extra()运行此代码时
MySQLdb.\u exceptions.operational错误:(1242,'子查询返回多行')
返回多行有什么问题?查询返回两行,因为我有两个产品,这是合理的。我想给每一种产品分配存货。
选择?建议?提示?

最佳答案

您正在尝试在外部查询和extra子查询之间进行联接,而数据库需要显式的join子句来实现这一点。我相信您可以在extra中添加WHERE子句以使其工作:

qs_productos.extra({
    "stock":
    """
        SELECT SUM(items.cantidad)
        FROM
            `encargosProveedor_listado_articulos` AS encargos,
            `itemArticulosProveedor`AS items, `articulos` as articulos
        WHERE
            articulos.producto_id = productos.id and
            encargos.itemarticulosproveedor_id=items.id and
            articulos.id=items.articulos_id
        GROUP BY articulos.producto_id
    """
})

productos中的articulos.producto_id = productos.id将需要替换为主查询中的实际表名。
由于extra被排成了弃用的队列(虽然从Django 2.2开始还没有完全弃用),下面是等效的RawSQL查询:
qs_productos.annotate(stock=RawSQL(
    """
        SELECT SUM(items.cantidad)
        FROM
            `encargosProveedor_listado_articulos` AS encargos,
            `itemArticulosProveedor`AS items, `articulos` as articulos
        WHERE
            articulos.producto_id = productos.id and
            encargos.itemarticulosproveedor_id=items.id and
            articulos.id=items.articulos_id
        GROUP BY articulos.producto_id
    """,
    ()
))

RawSQL中的空元组是必需的,因为该函数接受一个params元组参数,即使您没有要传递的参数,该参数也不是可选的。
另外,RawSQL对以前的values调用不太敏感,并在需要时提供可选的output_field参数。

关于python - 为什么django queryset.extra()抛出OperationalError:(1242,'Subquery返回多于1行')?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55755605/

10-12 19:27