大量嵌套查询

时间:2012-08-19 20:01:44

标签: mysql sql

SELECT 
productos.prod_id,
productos.prod_codigo1,
productos.prod_descripcion,
(SELECT SUM(cotdetalle.cotd_cantidad)
    FROM cotdetalle
    WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
    AND cotdetalle.cotd_cote_id IN(
            SELECT cotencabezado.cote_id
            FROM cotencabezado
            WHERE cotencabezado.cote_status = 'cerrada'
            AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
    )
) AS cuantos,
(SELECT SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio)
    FROM cotdetalle
    WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
    AND cotdetalle.cotd_cote_id IN(
            SELECT cotencabezado.cote_id
            FROM cotencabezado
            WHERE cotencabezado.cote_status = 'cerrada'
            AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
    )
) AS monto
FROM productos
ORDER BY monto DESC
LIMIT 0, 50

昨晚出现了这个问题,我想我的问题是:它太多了吗?我很确定还有其他方法可以在没有所有嵌套查询的情况下获得相同的结果。它可以工作但是我的开发环境需要一些时间,我敢打赌它会在生产环境上花费更多...任何建议? 如果您需要桌面结构,请告诉我......

编辑:实际上第二个SELECT最困扰我,它与第一个完全相同,但我需要第二个结果,但如果我尝试在第一个SELECT中获得第二个结果,它会给我“操作数”应包含1列“错误...

更多信息:我需要能够通过monto,cuantos,productos.prod_codigo1,productos.prod_descripcion

订购

sqlfiddle.com示例:http://sqlfiddle.com/#!2/c4391/1

3 个答案:

答案 0 :(得分:2)

您应该通过以下方式将此作为与组的简单连接:

SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion,
       t.quantos, t.monto
FROM productos p left outer join
     (SELECT cotdetalle.cotd_codigo, SUM(cotdetalle.cotd_cantidad) as quantos,
             SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio) as monto
      FROM cotdetalle
      WHERE cotdetalle.cotd_codigo = productos.prod_codigo1 and
            cotdetalle.cotd_cote_id IN
                (SELECT cotencabezado.cote_id
                 FROM cotencabezado
                 WHERE cotencabezado.cote_status = 'cerrada' and
                       MONTH(cotencabezado.cote_cierre) = MONTH(NOW()) AND 
                       YEAR(cotencabezado.cote_cierre) = YEAR(NOW()
               )
      group by cotdetalle.cotd_codigo
    ) t
    on t.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50

这应该改善一些事情。但是,MySQL在IN和子查询中表现不佳。因此,我们希望将其更改为连接,而不是子查询中的“IN”。请注意子查询中添加“distinct”。对于IN来说这不是必需的,但它适用于连接:

SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion,
       t.quantos, t.monto
FROM productos p join
     (SELECT cd.cotd_codigo, SUM(cd.cotd_cantidad) as quantos,
             SUM(cd.cotd_cantidad * cd.cotd_precio) as monto
      FROM cotdetalle cd join
           (SELECT distinct cc.cote_id
            FROM cotencabezado cc
            WHERE cc.cote_status = 'cerrada' and
                  MONTH(cc.cote_cierre) = MONTH(NOW()) AND 
                  YEAR(cc.cote_cierre) = YEAR(NOW()
           ) cc
           on cd.cotd_cote_id = cc.cote_id
      group by cd.cotd_codigo
    ) t
    on t.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50

我没有在SQL Fiddle上测试它,因此可能存在语法错误。

答案 1 :(得分:1)

为什么不将语句简化为

SELECT productos.prod_id,
productos.prod_codigo1,
productos.prod_descripcion,
( SELECT SUM(cotdetalle.cotd_cantidad) AS cuantos,
         SUM(cotdetalle.cotd_cantidad * cotdetalle.cotd_precio) AS monto
  FROM cotdetalle
  WHERE cotdetalle.cotd_codigo = productos.prod_codigo1
  AND cotdetalle.cotd_cote_id IN( SELECT cotencabezado.cote_id
                                  FROM cotencabezado
                                  WHERE cotencabezado.cote_status = 'cerrada'
                                  AND MONTH(cotencabezado.cote_cierre) = MONTH(NOW())
                                  AND YEAR(cotencabezado.cote_cierre) = YEAR(NOW())
                                 )
)
FROM productos 
ORDER BY monto DESC
LIMIT 0, 50

答案 2 :(得分:0)

好的,它结束了这样:

SELECT p.prod_id, p.prod_codigo1, p.prod_descripcion, t.cuantos, t.monto
FROM productos AS p
LEFT JOIN(
    SELECT cd.cotd_codigo,
    SUM(cd.cotd_cantidad) AS cuantos,
    SUM(cd.cotd_cantidad * cd.cotd_precio) AS monto
    FROM cotdetalle AS cd
    JOIN(
        SELECT DISTINCT ce.cote_id
        FROM cotencabezado AS ce
        WHERE ce.cote_status = 'cerrada'
        AND MONTH(ce.cote_cierre) = MONTH(NOW())
        AND YEAR(ce.cote_cierre) = YEAR(NOW())
    ) AS ce
    ON cd.cotd_cote_id = ce.cote_id
    GROUP BY cd.cotd_codigo
) AS t
ON cd.cotd_codigo = p.prod_codigo1
ORDER BY monto DESC
LIMIT 0, 50

根据Gordon Linoff的建议,这项工作要好得多,谢谢你!