我有一张桌子,可以提供每日库存状态。即库存项目X,在特定日期具有Y量的数量。我创建了一个功能,可以根据上次购买的价格获取特定日期的购买价格。
当我在dailyinventorystatus表上运行查询时,它会在3分钟内完成日期> 2014年1月1日。但是,当我将该函数作为子查询添加时,会导致巨大的性能问题。它已超过1.5小时,查询仍在运行。
如何改善这一点?
以下是查询:
SELECT
*,
RWReports.dbo.FindPurchasePrice(InventoryKey, Date , warehouse) as SalesPurchasePrice
FROM
DailyInventoryStatus
WHERE
Warehouse IN ('NYC,', 'CHICAGO', 'CHINA', 'ATLANTA')
AND Date >= '2014-01-01'
这是功能:
CREATE FUNCTION [dbo].[FindPurchasePrice]
(@InventoryKey varchar(8), @InDate Date , @Warehouse varchar(30))
RETURNS REAL
AS
BEGIN
DECLARE @oPurchasePrice AS REAL ;
SELECT TOP (1)
@oPurchasePrice = UnitPurchasePrice
FROM
PurchaseTransactions
WHERE
InventoryKey = @InventoryKey
AND TransactionDate <= @InDate
AND Warehouse = @Warehouse
ORDER BY
TransactionDate DESC;
IF @oPurchasePrice IS NULL
SELECT
@oPurchasePrice = mw.cost
FROM
Rentalworks.dbo.masterwh mw
JOIN
Rentalworks.dbo.warehouse w ON w.warehouseid = mw.warehouseid
AND mw.masterid = @InventoryKey
AND w.warehouse = @Warehouse;
RETURN @oPurchasePrice;
END;
GO
答案 0 :(得分:3)
这是你可以将它转换为内联表值函数的方法。
CREATE FUNCTION [dbo].[FindPurchasePrice]
(
@InventoryKey varchar(8)
, @InDate Date
, @Warehouse varchar(30)
)
RETURNS TABLE
AS
RETURN
SELECT ISNULL(pt.UnitPurchasePrice ,mw.cost) AS PurchasePrice
FROM Rentalworks.dbo.masterwh mw
JOIN Rentalworks.dbo.warehouse w on w.warehouseid = mw.warehouseid
AND mw.masterid = @InventoryKey
AND w.warehouse = @Warehouse
OUTER APPLY
(
SELECT TOP (1) UnitPurchasePrice
FROM PurchaseTransactions
WHERE InventoryKey = @InventoryKey
AND TransactionDate <= @InDate
AND Warehouse=@Warehouse
ORDER BY TransactionDate DESC
) pt
我当然无法对此进行测试,但语法检查很好。
现在要在原始的select语句中包含它,你可以这样做。
SELECT dis.*
, fp.PurchasePrice
FROM DailyInventoryStatus dis
CROSS APPLY dbo.FindPurchasePrice(dis.InventoryKey, dis.Date, dis.warehouse) fp
WHERE Warehouse IN ('NYC,', 'CHICAGO', 'CHINA', 'ATLANTA')
AND Date >= '2014-01-01'
答案 1 :(得分:0)
这是通过将所有逻辑合并到单个查询中而无需函数重写的一种方法:
with data as (
select
dis.*, pt.TransactionDate, pt.UnitPurchasePrice,
row_number() over (
partition by dis.InventoryKey, dis.Warehouse
order by TransactionDate desc
) as TransNumber
from
DailyInventoryStatus dis left outer join
PurchaseTransactions pt
on pt.InventoryKey = dis.InventoryKey
and pt.Warehouse = dis.Warehouse
and pt.TransactionDate < dis.Date
where dis.Date >= ?
)
select
*,
coalesce(
UnitPurchasePrice,
(
select mw.cost
from
Rentalworks.dbo.masterwh mw inner join
Rentalworks.dbo.warehouse w
on w.warehouseid = mw.warehouseid
where mw.masterid = data.InventoryKey
and w.warehouse = data.Warehouse
)
) as PurchasePrice
from data
where TransNumber = 1