高效的T-SQL,用于添加具有先前值的缺失日期

时间:2012-01-20 23:30:17

标签: sql-server-2005 tsql

我有一个表格,显示项目的库存变化,如此

Item_ID | Date_ID   | Change | Inventory
 521    | 5/1/2010  | 56     | 56
 634    | 5/2/2010  | -12    | 42
 521    | 5/12/2010 | 3      | 59

我有一个LU_Date表和一个包含所有项目的LU_Item表(清单表中可能存在也可能不存在。)

我需要输出显示所有项目的所有日期,当天有库存,例如:

Item_ID | Date_ID   | Change | Inventory
521     | 4/30/2010 | 0      | 0
521     | 5/1/2010  | 56     | 56
521     | 5/2/2010  | 0      | 56
521     | 5/3/2010  | 0      | 56
521     | 5/4/2010  | 3      | 59
634     | 4/30/2010 | 0      | 54
634     | 5/1/2010  | 0      | 54
634     | 5/2/2010  | -12    | 42
632     | 4/30/2010 | 0      | 0

我尝试过解决方案,但似乎无法找到有效的查询。使用这样的解决方案时:

SELECT d.Date_ID,
ISNULL(r.Change,0) AS mnmt,
COALESCE(r.Inventory, S.Inventory) AS quantity
FROM dbo.LU_Date d 
CROSS JOIN LU_Item i
LEFT JOIN Fact_Inventory_ByDay r ON d.Date_ID=r.Date_ID AND r.Item_ID=i.Item_ID
OUTER APPLY (SELECT TOP(1) Inventory
           FROM Fact_Inventory_ByDay b2 
           WHERE b2.Item_ID=i.Item_ID AND b2.Date_ID < d.Date_ID 
           ORDER BY b2.Date_ID DESC, b2.Item_ID DESC) AS S
    WHERE i.item_ID=@Item

我得到了不可接受的等待时间(例如,单个项目为46秒)。 有没有人对我有优雅的解决方案?

谢谢!

1 个答案:

答案 0 :(得分:0)

我能想到的最快的优化是将缺少的库存行的提取移动到仅运行所需行的第二个查询中。

给它一个镜头(这是徒手画,所以可能会填充错误)

我认为Fact_Inventory_ByDay上的主键是Inventory_ByDay_ID,也不确定同一天是否有多个库存更改,因此将其计算在内。

SELECT
    D.Date_ID,
    I.Item_ID,
    COALESCE(SUM(FI.Change),0) AS Change,
    MAX(FI.Inventory_ByDay_ID) as MaxID,
INTO #TempRows
FROM
    dbo.LU_Date D
    JOIN LU_Item I
      ON I.Item_ID = @ItemID
    LEFT JOIN Fact_Inventory_ByDay FI
      ON FI.Date_ID = D.Date_ID AND FI.Item_ID = I.Item_ID
GROUP BY
    D.Date_ID,
    I.Item_ID


UPDATE
    #TempRows T
SET
    T.MaxID = ( SELECT TOP 1 FI.Inventory_ByDay_ID 
                FROM Fact_Inventory_ByDay FI
                WHERE FI.Date_ID < T.Date_ID
                AND FI.Item_ID = T.Item_ID
                ORDER BY FI.Date_ID DESC )
WHERE
    T.MaxID is NULL


SELECT
    T.Date_ID,
    T.Item_ID,
    T.Change,
    FI.Inventory
FROM 
    #TempRows
    JOIN Fact_Inventory_ByDay FI
      ON FI.Inventory_ByDay_ID = T.Inventory_ByDay_ID