加入子查询以获取开始和结束提供日期优化的数据

时间:2016-05-12 07:46:44

标签: sql sql-server tsql join sql-server-2008-r2

我正在使用 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 

2 个答案:

答案 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