我正在使用 SQL-Server 2008 。
我必须在提供的开始日期和2个仓库提供的结束日期的物品库存中选择物品库存。
这就是我为QuantityStock
选择@startDate
的方式:
DECLARE @startDate DATE = '20160111'
SELECT *
FROM (
SELECT SUM(QuantityStock) AS QuantityStockStart, Vendor, ItemNo, Company, [Date]
FROM WarehouseA wha
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseA wha2
WHERE wha.Vendor = wha2.Vendor
AND wha.ItemNo = wha2.ItemNo
AND wha.Company= wha2.Company
AND [Date] <= @startDate)
GROUP BY Vendor, ItemNo, Company, [Date]
UNION ALL
SELECT SUM(QuantityStock) AS QuantityStockStart, Vendor, ItemNo, Company, [Date]
FROM WarehouseB whb
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseB whb2
WHERE whb.Vendor = whb2.Vendor
AND whb.ItemNo = whb2.ItemNo
AND whb.Company= whb2.Company
AND [Date] <= @startDate)
GROUP BY Vendor, ItemNo, Company, [Date]
) stock_start
LEFT JOIN some_table st ON.....
如您所见,有两个类似的查询,只需从不同的表中进行选择,为此我使用UNION ALL
此外我还在使用[DATE] <= @startDate
,因为并非每天剩余的库存都在插入,因此对于提供的日期'20160111'
,可能没有数据,因此需要选择剩余库存为的最长日期插入
上面的查询有点慢,但工作正常。
问题是我需要对@endDate做同样的事情以获得结束日期的剩余库存。查询与上述类似,而不是@startDate
我需要使用@endDate
。
我已尝试使用上述查询和LEFT JOIN
类似查询,只需使用@endDate
代替@startDate
:
DECLARE @startDate DATE = '20160111',
@endDate DATE = '20165112'
SELECT stock_start.*, stock_end.QuantityStockEnd
FROM (
SELECT SUM(QuantityStock) AS QuantityStockStart, Vendor, ItemNo, Company, [Date]
FROM WarehouseA wha
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseA wha2
WHERE wha.Vendor = wha2.Vendor
AND wha.ItemNo = wha2.ItemNo
AND wha.Company= wha2.Company
AND [Date] <= @startDate)
GROUP BY Vendor, ItemNo, Company, [Date]
UNION ALL
SELECT SUM(QuantityStock) AS QuantityStock, Vendor, ItemNo, Company, [Date]
FROM WarehouseB whb
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseB whb2
WHERE whb.Vendor = whb2.Vendor
AND whb.ItemNo = whb2.ItemNo
AND whb.Company= whb2.Company
AND [Date] <= @startDate)
GROUP BY Vendor, ItemNo, Company, [Date]
) stock_start
LEFT JOIN (
SELECT SUM(QuantityStock) AS QuantityStockEnd, Vendor, ItemNo, Company, [Date]
FROM WarehouseA wha
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseA wha2
WHERE wha.Vendor = wha2.Vendor
AND wha.ItemNo = wha2.ItemNo
AND wha.Company= wha2.Company
AND [Date] <= @endDate)
GROUP BY Vendor, ItemNo, Company, [Date]
UNION ALL
SELECT SUM(QuantityStock) AS QuantityStockEnd, Vendor, ItemNo, Company, [Date]
FROM WarehouseB whb
WHERE [Date] = (SELECT MAX([Date])
FROM WarehouseB whb2
WHERE whb.Vendor = whb2.Vendor
AND whb.ItemNo = whb2.ItemNo
AND whb.Company= whb2.Company
AND [Date] <= @endDate)
GROUP BY Vendor, ItemNo, Company, [Date]
) stock_end ON stock_start.Vendor = stock_end.Vendor AND stock_start.ItemNo = stock_end.ItemNo AND stock_start.Company = stock_end.Company
LEFT JOIN some_table st ON.....
通过这种方式,我获得了理想的结果,但是它的执行时间如此之高(仅比使用@startDate
的第一次查询长约10倍)。你有什么想法我可以优化吗?看起来应该有任何其他更简单的方法,而不重复代码...
所以最终结果应该是:
QuantityStockStart | Vendor | ItemNo | Company | [Date] | QuantityStockEnd
答案 0 :(得分:3)
我建议使用分析函数ROW_NUMBER()来定位所需的源表行。虽然没有可以测试的样本数据,但是我认为你可以做到这一点:
SELECT
whab.Vendor
, whab.ItemNo
, whab.Company
, MIN(CASE WHEN whab.start_rn = 1 THEN whab.[Date] END) start_dt
, SUM(CASE WHEN whab.start_rn = 1 THEN whab.QuantityStock END) qty_at_start
, MAX(CASE WHEN whab.end_rn = 1 THEN whab.[Date] END) end_dt
, SUM(CASE WHEN whab.end_rn = 1 THEN whab.QuantityStock END) qty_at_end
FROM (
SELECT
Vendor
, ItemNo
, Company
, [Date]
, QuantityStock
, ROW_NUMBER() OVER (PARTITION BY Vendor, ItemNo, Company
ORDER BY CASE WHEN [Date] <= @startDate THEN 1 ELSE 2 END, [Date] DESC) AS start_rn
, ROW_NUMBER() OVER (PARTITION BY Vendor, ItemNo, Company
ORDER BY CASE WHEN [Date] <= @endDate THEN 1 ELSE 2 END, [Date] DESC) AS end_rn
FROM WarehouseA
UNION ALL
SELECT
Vendor
, ItemNo
, Company
, [Date]
, QuantityStock
, ROW_NUMBER() OVER (PARTITION BY Vendor, ItemNo, Company
ORDER BY CASE WHEN [Date] <= @startDate THEN 1 ELSE 2 END, [Date] DESC) AS start_rn
, ROW_NUMBER() OVER (PARTITION BY Vendor, ItemNo, Company
ORDER BY CASE WHEN [Date] <= @endDate THEN 1 ELSE 2 END, [Date] DESC) AS end_rn
FROM WarehouseB
) whab
WHERE whab.start_rn = 1
OR whab.end_rn = 1
GROUP BY
whab.Vendor
, whab.ItemNo
, whab.Company
答案 1 :(得分:0)
尝试删除WHERE [Date]=
后面的子查询,但保留该子查询中的where条件。将[Date]
更改为MAX([Date])
,并从用于使用已删除子查询的查询中的[Date]
中删除GROUP BY
。