2014-10-20 210 views
0

讓我們假設您需要跟蹤採購訂單項目交付在給定時間段內的演變情況,並且由於某種原因,此交付可能會遭遇逆轉。比起你有一個表,至少有這些字段來存儲你需要的數據:PO,POItem,QtyDelivered,DateFrom,DateTo,顯然你可能想要保存更多關於某個項目的數據,但是我省略了一些字段來簡化說明。 QtyDelivered字段包含累計交貨金額,該字段從0到您PO中請求的金額,因此如果您的採購訂單有100個物料單位的請求,QtyDelivered將從0到100。但是,如果交貨遭受逆轉,這使得QtyDelivered遭受減少。 DateFrom和DateTo保存了QtyDelivered保持相同值的日期間隔。假設表包含下面這些記錄:計算一段時間內兩行之間的差異

OBS:插入順序並不總是服從,這就是爲什麼我搞砸了標識的

 
Id  PO  POItem  QtyDelivered  DateFrom  DateTo 
    3 4500000000 10    39   15/10/2014 15/10/2014 
    4 4500000000 10    60   15/10/2014 15/10/2014 
    1 4500000000 10    55   01/10/2014 13/10/2014 
    7 4500000001 10    40   16/10/2014 17/10/2014 
    5 4500000001 10    5   14/10/2014 16/10/2014 
    6 4500000001 10    36   16/10/2014 16/10/2014 
    2 4500000000 10    5   13/10/2014 15/10/2014 
    8 4500000001 10    2   17/10/2014 18/10/2014 

現在假設你需要知道的給定材料的多少個單位已於2014年10月2日至2014年10月14日交付。那麼,從2014年10月1日到2013年10月13日,採購訂單4500000000件10的交貨量爲55件,從2014年10月13日到2014年10月15日,這件商品的交貨量爲5件,因爲它遭受了逆轉,所以有-50的負變化。請注意,在這種情況下,您選擇的時間段在兩條記錄的DateFrom和DateTo之間,但如果您選擇了2014年10月1日至2014年10月18日,該怎麼辦?在這種情況下,您選擇的時間段包含記錄的DateFrom和DateTo日期。如何構建一個查詢來計算給定時間段內的QtyDelivered之間的差異?

回答

1
SELECT 
Table.PO 
,Table.POItem 
,(SELECT QtyDelivered 
    FROM Table 
    WHERE Id = TblId.MaxId) - (SELECT QtyDelivered 
          FROM Table 
          WHERE Id = TblId.MinId) AS [Qty delivered] 
FROM Table 
INNER JOIN(SELECT 
      MIN(Id) AS MinId 
      ,MAX(Id) AS MaxId 
      FROM Table 
      WHERE 
       (DateFrom >= @DateFrom AND DateTo <= @DateTo) 
      OR 
       ((@DateFrom BETWEEN DateFrom AND DateTo 
        OR @DateTo BETWEEN DateFrom AND DateTo 
       ) 
       AND DateTo <> @DateFrom 
       AND DateFrom <> @DateTo 
       ) 
      GROUP BY 
      PO 
      ,POItem) AS TblId 
ON TblId.MaxId = Table.Id 

注意,內部聯接子查詢只返回MIN和MAX ID,用於聯接發生,僅是所選擇的報告期裏面記錄過濾。它顯着減少了要加入的記錄數量,因爲過濾是在聯接本身之前完成的。計算字段是子查詢,它使用由內部聯接子查詢返回的Id來查找第一個和最後一個記錄以計算它們之間的差異。

在內部連接子查詢中,where子句有點複雜但易於理解。請注意,系統用戶選擇的時間段可以介於記錄的日期和記錄的日期之間,也可以涵蓋記錄的日期和日期之間。因此,第一個條件(DateFrom> = @DateFrom AND DateTo < = @DateTo)保證查詢返回所選期間所涵蓋的所有記錄。 OR部分保證,所選記錄中的日期在記錄的日期和日期之間的所有記錄都將被返回。但需要排除To date等於所選期間的第一個日期並且From Date等於所選期間的最後日期的記錄,因此OR部分內的AND部分將保證(DateTo < > @DateFrom和DateFrom <> @DateTo)。連接條件ON TblId.MaxId = Table.Id使得連接發生在關於滿足所選週期的每條記錄的最後一個Id中,因此您具有每條記錄的最終狀態。