【发布时间】:2023-03-17 23:03:01
【问题描述】:
我使用 SQL Server 2008 。 我尝试制作报告,需要计算我表中每一行的新列。 我写了这个函数:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
ALTER FUNCTION [dbo].[fn_CalcProductStock]
(
@ProductID INT = NULL ,
@ToDate DATETIME = NULL ,
@FinYear INT = NULL ,
@InventoryID INT = NULL
)
RETURNS FLOAT
AS
BEGIN
DECLARE @stock FLOAT
SET @stock = ISNULL(( SELECT SUM(IDI.InvDocItemNumbers)
FROM InvDocItem IDI
LEFT OUTER JOIN InvDoc ID ON IDI.CenterID = ID.CenterID
AND IDI.InvDocID = ID.InvDocID
WHERE IDI.ProductID = @ProductID
AND ID.FinYearID = @FinYear
AND ( ID.InventoryID = @InventoryID
OR @InventoryID IS NULL
)
AND ID.InvDocDate < @ToDate
AND ( ID.InvTransTypeID = 1
OR ID.InvTransTypeID = 4
OR ID.InvTransTypeID = 6
OR ID.InvTransTypeID = 13
OR ID.InvTransTypeID = 9
)
), 0)
- ISNULL(( SELECT SUM(II.InvoiceItemNumbers)
FROM InvoiceItem II
LEFT OUTER JOIN Invoice I ON ( II.CenterID = I.CenterID
AND II.InvoiceID = I.InvoiceID
)
WHERE II.ProductID = @ProductID
AND I.FinYearId = @FinYear
AND I.InvoiceDate < @ToDate
AND ( I.InventoryID = @InventoryID
OR @InventoryID IS NULL
) --Tehran:1 Tehrantakh:101 Mashhad:21 Tabriz:6
AND ( I.InvoiceType = 1
OR I.InvoiceType = 3
)
), 0)
+ ISNULL(( SELECT SUM(II.InvoiceItemNumbers)
FROM InvoiceItem II
LEFT OUTER JOIN Invoice I ON II.CenterID = I.CenterID
AND II.InvoiceID = I.InvoiceID
WHERE II.ProductID = @ProductID
AND I.FinYearId = @FinYear
AND I.InvoiceDate < @ToDate
AND ( I.InventoryID = @InventoryID
OR @InventoryID IS NULL
)
AND ( I.InvoiceType = 2
OR I.InvoiceType = 4
)
), 0)
- ISNULL(( SELECT SUM(IDI.InvDocItemNumbers)
FROM InvDocItem IDI
LEFT OUTER JOIN InvDoc ID ON IDI.CenterID = ID.CenterID
AND IDI.InvDocID = ID.InvDocID
WHERE IDI.ProductID = @ProductID
AND ID.InvTransTypeID = 3
AND ID.FinYearID = @FinYear
AND ( ID.InventoryID = @InventoryID
OR @InventoryID IS NULL
)
AND ID.InvDocDate < @ToDate
), 0)
-- Return the result of the function
RETURN @stock
END
在这种情况下,我也尝试使用此功能:
SELECT Prdct.InventoryID ,
Prdct.ProductID ,
( dbo.fn_CalcProductStock(Prdct.ProductID, '2014-04-29', 92, 101) )
FROM ProductInv AS Prdct
这有真实的计算结果,但需要很长时间 就像40分钟......!!!适用于 3000 种产品
我怎样才能使它的性能更好?
【问题讨论】:
-
除了任何性能问题之外,您的函数可能没有按您想要的方式运行。唯一可以安全忽略的变量是
InventoryId。FinYear和ToDate将需要一个值来返回 any 结果。ProductId条件的定位意味着连接实际上是INNER JOINs - 如果您不提供值,您也不会得到任何结果(因为null不等于 @ 987654329@)。您的查询似乎获得了 quantity 的项目,但对我而言,ItemNumber本质上是一个 key - 这只是一个命名模糊的变量,还是一个计数? -
它是发票或文档中每个产品的计数..
标签: sql sql-server performance sql-server-2008 tsql