没有EXISTS优化SQL查询

时间:2016-04-28 10:32:12

标签: mysql sql sql-server

我有4张桌子,F_NSE,F_LTR,F_TRA,INVENTARIO。

表INVENTARIO包含产品最后库存的数据。 F_NSE是产品可转换性表(bacth date,..),F_LTR包含产品销售数据,F_TRA包含INVOICE数据。我需要从INVENTARIO表的最后日期开始计算产品的实际库存。

一个产品可以在INVETARIO表中排成行。

问题在于查询中的NOT EXISTS子句,不是优化:

SELECT T0.NSENSE AS LOTE, REPLACE(REPLACE(CONVERT(VARCHAR, T0.FCONSE, 103), '01/01/1900', ''), '/20', '/') AS FCONSE,
SUM(T0.CANNSE) AS UNIDADES, T2.AORTRA AS CODALM,  T1.ARTLTR
FROM F_NSE AS T0 
INNER JOIN F_LTR AS T1 ON T0.DOCNSE = 'TR' AND T0.TIPNSE = ''
    AND T0.CODNSE = T1.DOCLTR AND T0.POSNSE = T1.LINLTR 
INNER JOIN F_TRA AS T2 ON T2.DOCTRA = T1.DOCLTR
LEFT OUTER JOIN Stock_Inventario_Pruebas AS T3 ON T3.CODART = T1.ARTLTR 
                    AND T3.CODALM = T2.AORTRA AND T3.NSENSE = T0.NSENSE 
WHERE (
  NOT EXISTS
    (SELECT INVENTARIO
    FROM dbo.ERP_Stock_Inventario_Pruebas AS T3
    WHERE (T1.ARTLTR = CODART))) AND
    T1.ARTLTR ='125554705' OR T2.FECTRA > T3.INVENTARIO 
    AND T1.ARTLTR = '125554705' 
    GROUP BY T0.NSENSE, T0.FCONSE, T1.ARTLTR,T2.AORTRA
    )
  )

2 个答案:

答案 0 :(得分:2)

我重写了查询,所以我觉得它更容易阅读:

SELECT T0.NSENSE AS LOTE,
       REPLACE(REPLACE(CONVERT(VARCHAR(255), T0.FCONSE, 103), '01/01/1900', ''), '/20', '/') AS FCONSE, 
       SUM(T0.CANNSE) AS UNIDADES, 
       T2.AORTRA AS CODALM, T1.ARTLTR
FROM F_NSE T0 INNER JOIN
     F_LTR T1
     ON T0.DOCNSE = 'TR' AND T0.TIPNSE = '' AND
        T0.CODNSE = T1.DOCLTR AND T0.POSNSE = T1.LINLTR INNER JOIN
     F_TRA T2
     ON T2.DOCTRA = T1.DOCLTR LEFT OUTER JOIN
     Stock_Inventario_Pruebas T3
     ON T3.CODART = T1.ARTLTR AND T3.CODALM = T2.AORTRA AND T3.NSENSE = T0.NSENSE 
WHERE T1.ARTLTR ='125554705' AND
      (NOT EXISTS (SELECT 1
                   FROM dbo.ERP_Stock_Inventario_Pruebas T3
                   WHERE T1.ARTLTR = T3.CODART
                  ) OR
       T2.FECTRA > T3.INVENTARIO 
      )
GROUP BY T0.NSENSE, T0.FCONSE, T1.ARTLTR,T2.AORTRA;

对于此查询,我建议在F_LTR(ARTLTR)ERP_Stock_Inventario_Pruebas(CODART)上建立索引。

我确实想知道为什么左连接使用的列数多于NOT EXISTS。更典型的逻辑看起来像这样:

. . .
     Stock_Inventario_Pruebas T3
     ON T3.CODART = T1.ARTLTR AND T2.FECTRA > T3.INVENTARIO 
WHERE T1.ARTLTR ='125554705' 
. . .

这与您的查询无关;它对我来说更有意义。

答案 1 :(得分:0)

我认为这相当于重述SQL,但没有相关的子查询。将(主键)替换为必填字段名称,以便您知道它是否缺失,连接缺失。

SELECT T0.NSENSE AS LOTE,
       REPLACE(REPLACE(CONVERT(VARCHAR(255),
       T0.FCONSE, 103), '01/01/1900', ''), '/20', '/') AS FCONSE, 
       SUM(T0.CANNSE) AS UNIDADES, 
       T2.AORTRA AS CODALM,
       T1.ARTLTR

FROM F_NSE T0 

INNER JOIN F_LTR T1
     ON T0.DOCNSE = 'TR' 
     AND T0.TIPNSE = '' 
     AND T0.CODNSE = T1.DOCLTR 
     AND T0.POSNSE = T1.LINLTR 

INNER JOIN F_TRA T2
     ON T2.DOCTRA = T1.DOCLTR 

LEFT OUTER JOIN Stock_Inventario_Pruebas T3
     ON T3.CODART = T1.ARTLTR 
     AND T3.CODALM = T2.AORTRA 
     AND T3.NSENSE = T0.NSENSE 

LEFT OUTER JOIN dbo.ERP_Stock_Inventario_Pruebas T4
    ON T1.AR√LTR = T4.CODART

WHERE T4.(primary key) IS NULL
    OR T2.FECTRA > T3.INVENTARIO 

GROUP BY T0.NSENSE, T0.FCONSE, T1.ARTLTR,T2.AORTRA;