如何替换函数以更快地进行查询?

时间:2018-01-09 16:02:29

标签: sql sql-server

我试图在不使用功能的情况下进行查询,因为它需要花费太多时间来提供结果。这是包含函数和结果的代码。

SELECT  
LEFT(D2.D2_EMISSAO,6),
F2.F2_VEND1,
SUM((D2.D2_TOTAL-dbo.UCOMPRA(D2.D2_COD, D2.D2_EMISSAO)*D2.D2_QUANT)) AS  LUCRO_LIQ
FROM SD2010 D2                
INNER JOIN SF2010 F2 
    ON D2.D2_DOC = F2.F2_DOC AND D2.D2_SERIE = F2.F2_SERIE AND F2.D_E_L_E_T_= ''
WHERE 
D2.D2_EMISSAO >=  '20171201'
AND D2.D2_TES IN ('502','506')
GROUP BY 
LEFT(D2.D2_EMISSAO,6),
F2.F2_VEND1
ORDER BY F2.F2_VEND1 DESC

这是功能:

ALTER FUNCTION dbo.UCOMPRA( @CODIGO VARCHAR(25), @DATE VARCHAR(8))
RETURNS float

 BEGIN
 DECLARE @UPRECO float;

    SELECT TOP 1 @UPRECO = ROUND(D1.D1_CUSTO/D1.D1_QUANT,2)
    FROM SD1010 D1  
   WHERE D1.D_E_L_E_T_ = ''        
       AND D1.D1_TES  IN('015','202','205','206')
           AND D1.D1_COD = @CODIGO 
           AND D1.D1_EMISSAO <= @DATE 
      ORDER BY D1.D1_EMISSAO DESC ;  

RETURN ROUND(@UPRECO,2);
END;
GO

使用函数

的查询结果

enter image description here

我试过这个:

SELECT  D2.D2_EMISSAO,
D2.D2_DOC,
D2.D2_COD,
D2.D2_QUANT,
D2.D2_PRCVEN, 
D2.D2_TOTAL, 
ENTRADA.CUSTO,
((D2.D2_TOTAL/D2.D2_QUANT-ENTRADA.CUSTO)*D2.D2_QUANT) AS  LUCRO_LIQ

FROM SD2010 D2
LEFT JOIN SD1010 D1 ON D2.D2_COD=D1.D1_COD
INNER JOIN (SELECT D1.D1_COD AS COD,D1.D1_TOTAL AS D1TOTAL, 
D1.D1_TOTAL/D1.D1_QUANT AS CUSTO
        FROM SD1010 D1 
        WHERE 
        D1.D1_EMISSAO <= '20171201'
        AND D1.D1_TES IN ('015','202','205','206')
        AND D1.D_E_L_E_T_='') ENTRADA
        ON D2.D2_COD = ENTRADA.COD


  WHERE D2.D2_COD = '000712S3B70340'
  AND D1.D1_EMISSAO <= D2.D2_EMISSAO
  AND D2.D2_TES IN ('502','506')
  ORDER BY D2.D2_DOC DESC

Result of the code without You can see that the value from "lucro_liq" is diferent

1 个答案:

答案 0 :(得分:2)

结果的差异是因为您在函数中使用Order by,但在sub-select中没有order by。通过内部子选择添加顺序也没有任何意义。

我希望inline table valued功能优于scalar功能

DROP FUNCTION dbo.Ucompra

go

CREATE FUNCTION dbo.Ucompra(@CODIGO VARCHAR(25),
                            @DATE   VARCHAR(8))
RETURNS TABLE
    RETURN
      (SELECT TOP 1 UPRECO = Round(D1.D1_CUSTO / D1.D1_QUANT, 2)
       FROM   SD1010 D1
       WHERE  D1.D_E_L_E_T_ = ''
              AND D1.D1_TES IN( '015', '202', '205', '206' )
              AND D1.D1_COD = @CODIGO
              AND D1.D1_EMISSAO <= @DATE
       ORDER  BY D1.D1_EMISSAO DESC)

GO

SELECT LEFT(D2.D2_EMISSAO, 6),
       F2.F2_VEND1,
       Sum(( D2.D2_TOTAL - oa.UPRECO * D2.D2_QUANT )) AS LUCRO_LIQ
FROM   SD2010 D2
       INNER JOIN SF2010 F2
               ON D2.D2_DOC = F2.F2_DOC
                  AND D2.D2_SERIE = F2.F2_SERIE
                  AND F2.D_E_L_E_T_ = ''
       OUTER apply dbo.Ucompra(D2.D2_COD, D2.D2_EMISSAO) oa
WHERE  D2.D2_EMISSAO >= '20171201'
       AND D2.D2_TES IN ( '502', '506' )
GROUP  BY LEFT(D2.D2_EMISSAO, 6),
          F2.F2_VEND1
ORDER  BY F2.F2_VEND1 DESC