【问题标题】:How to improve/simplify a query with a lot of subquerys?如何改进/简化具有大量子查询的查询?
【发布时间】:2019-07-03 19:09:41
【问题描述】:

我有一个 sql 查询,它对我的​​数据库中的一些寄存器进行求和和计数,问题是我使用了很多子查询并且它们都具有相同的条件,我需要找到一个更好的解决方案,因为这会导致我的系统运行缓慢。

我尝试使用简单的左连接,但 mysql 返回了一行,我希望对表 dbgeneralesImportacion 上的每个寄存器进行计数和求和。

我有这样的事情:

SELECT  dbgeneralesImportacion.id,
        sapito.dbgeneralesImportacion.documentosCompletos AS 'documentosCompletos', 
        (SELECT COUNT(c.id) 
        FROM sapito.dbcontenedores c 
        WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorContenedores', 
        (SELECT SUM(IF(c.estatus = 1, 1, 0)) 
        FROM sapito.dbcontenedores c 
        WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorDespachos', 
        (SELECT SUM(IF(c.estatus = 2, 1, 0)) 
        FROM sapito.dbcontenedores c 
        WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorCompletado', 
        (SELECT SUM(IF(c.desconsolidacion = 1, 1, 0)) 
        FROM sapito.dbcontenedores c 
        WHERE c.operacion = dbgeneralesImportacion.id ) AS 'DesconsolidacionPuerto',
        (SELECT SUM(c.bultos) FROM sapito.dbcontenedores c WHERE c.operacion = dbgeneralesImportacion.id)  AS 'bultos'
FROM    dbgeneralesImportacion

And my idea was to do this but counts all register and return a single row:

SELECT  dbgeneralesImportacion.id AS 'id',
        COUNT(c.id) AS 'ContadorContenedores', 
        SUM(IF(c.estatus = 1, 1, 0))  AS 'ContadorDespachos', 
        SUM(IF(c.estatus = 2, 1, 0))  AS 'ContadorCompletado', 
        SUM(IF(c.desconsolidacion = 1, 1, 0))  AS 'DesconsolidacionPuerto',
        SUM(c.bultos)  AS 'bultos'
FROM    dbgeneralesImportacion
        LEFT JOIN dbcontenedores c ON c.operacion = dbgeneralesImportacion.id

Thank you everyone

【问题讨论】:

  • 如果您使用 MySQL 8.x,您可以使用 CTE 重用子查询。
  • 在我的个人电脑上我使用的是 MYSQL 8 但服务器有 5.7 版本

标签: mysql sql database subquery


【解决方案1】:

你可以使用 join a 和 group by

     SELECT  a.id
         , a.documentosCompletos
         , COUNT(c.id) ContadorContenedores
         , SUM(IF(c.estatus = 1, 1, 0)) ContadorDespachos
         , SUM(IF(c.estatus = 2, 1, 0)) ContadorCompletado
         , SUM(IF(c.desconsolidacion = 1, 1, 0)) DesconsolidacionPuerto
         ,  SUM(c.bultos) bultos

     FROM    dbgeneralesImportacion a
     INNER JOIN sapito.dbcontenedores c ON c.operacion = a.id
     GRUP BY a.id, a.documentosCompletos

【讨论】:

  • 成功了!!非常感谢,JoshGivens 的回答也有效,可惜我只能选择一个答案
  • @AlejandroCoronadoRubio .. 这是 SO .. 选择更好的,或者如果是相似的 coose 第一个 ..
【解决方案2】:

不肯定,但你不能这样做

SELECT  dbgeneralesImportacion.id,
sapito.dbgeneralesImportacion.documentosCompletos AS 'documentosCompletos', 
COUNT(c.id)  AS 'ContadorContenedores', 
SUM(IF(c.estatus = 1, 1, 0)) AS 'ContadorDespachos', 
SUM(IF(c.estatus = 2, 1, 0)) AS 'ContadorCompletado', 
SUM(IF(c.desconsolidacion = 1, 1, 0)) AS 'DesconsolidacionPuerto',
SUM(c.bultos) AS 'bultos'

FROM    dbgeneralesImportacion, sapito.dbcontenedores c

WHERE c.operacion = dbgeneralesImportacion.id 
GROUP BY dbgeneralesImportacion.id

【讨论】:

  • 效果很好!!,非常感谢!!!但我只能选择一个答案:(
  • 一切都很好,另一个答案比我的略好,因为它使用了正确的连接,而不是仅仅在 where 子句中链接它们。
【解决方案3】:

您需要GROUP BY,但您也可以简化查询:

SELECT gi.id AS id,
       COUNT(c.id) AS ContadorContenedores, 
       SUM( c.estatus = 1 )  AS ContadorDespachos, 
       SUM( c.estatus = 2 )  AS ContadorCompletado, 
       SUM( c.desconsolidacion = 1 )  AS DesconsolidacionPuerto,
       SUM(c.bultos)  AS bultos
FROM dbgeneralesImportacion LEFT JOIN
     dbcontenedores c 
     ON c.operacion = gi.id
GROUP BY gi.id;

MySQL 将布尔值视为数字上下文中的数字,true 为 1,false 为 0。这使得计算匹配值变得容易。

此外,仅对字符串和日期常量使用单引号。将它们用于列别名可能会导致难以调试的问题。

【讨论】:

  • 但是当 dbcontenedores 中的字段为 null 时使用这种方式返回 null,如果我使用我首先执行的方式它返回 0,这不是最佳做法,但数据库在外部服务器中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
相关资源
最近更新 更多