2009-10-23 29 views
0

我有一個包含訂單表和庫存表的數據庫。

訂單商品表每1個數量的佈局有1條記錄,所以如果一個人下單7'ABC和4'XYZ的訂單,我會得到11個記錄。隊列數量的SQL查詢幫助

 
id, item, qtyNum 
01 ABC 1 
02 ABC 2 
03 ABC 3 
04 ABC 4 
05 ABC 5 
06 ABC 6 
07 ABC 7 
08 XYZ 1 
09 XYZ 2 
10 XYZ 3 
11 XYZ 4 

庫存表中有一個量/項目每個位置的佈局,這樣我就可以有庫存的東西20,但它可以(在最壞的情況下),在20個不同的地點。因此,對於我們的示例,我可能有以下庫存:

 
Qty, Item,    Loc,   Date 
3 'ABC' in Location L1 with date 1990 
2 'ABC' in Location L2 with date 1992 
5 'ABC' in Location L3 with date 2003 
4 'ABC' in Location LH with date 2004 
1 'XYZ' in Location L4 with date 1990 
2 'XYZ' in Location L5 with date 1993 
9 'XYZ' in Location L6 with date 2001 
2 'XYZ' in Location LJ with date 2004 

* H和J沒有特別意義!只要驅動點回家,他們是最新

結果集應該拉儘可能多的從最老的位置上的第一,所以在這個例子中我結束了以下「挑選隊列」:

 
Pick 3 'ABC' from L1 
Pick 2 'ABC' from L2 
Pick 2 'ABC' from L3 
Pick 1 'XYZ' from L4 
Pick 2 'XYZ' from L5 
Pick 1 'XYZ' from L6 

我的確有一個解決方案,它涉及到很多視圖,這些視圖通過外連接和瘋狂的東西連接多次,我只是很好奇這個問題是否存在簡單/優雅的解決方案?我可以在代碼中做到這一點沒有問題,但在SQL中我不是大師。
MSSQL 2008

+0

在你的訂單商品表中,qtyNum應該增加每一行,或者每行應該是1。如果他們下訂單7個ABC項目,看起來好像你認爲該表格會顯示28個數量。或者我誤解了qtyNum專欄的觀點? – 2009-10-23 18:36:04

+0

它只是提供項目順序的額外數據。其類似項目ID 10是該訂單中項目「XYZ」的第三數量。 對於所有的意圖和目的,可能只是忽略qtyNum – Hatch 2009-10-23 18:41:25

回答

0

哎,這對我來說是艱難的;我敢肯定有比這更優雅的解決方案,但是這是我想出了:

--test data 
DECLARE @orders TABLE 
    (
     ID INT IDENTITY(1, 1) , 
     item CHAR(3) , 
     Qty INT 
    ) 
INSERT INTO @orders 
     (item, Qty) 
VALUES ('abc', 1), 
     ('abc', 2), 
     ('abc', 3), 
     ('abc', 4), 
     ('abc', 5), 
     ('abc', 6), 
     ('abc', 7), 
     ('xyz', 1), 
     ('xyz', 2), 
     ('xyz', 3), 
     ('xyz', 4) 

DECLARE @ItemLoc TABLE 
    (
     Qty INT , 
     ITEM CHAR(3) , 
     Loc CHAR(2) , 
     Dt INT 
    ) 
INSERT INTO @ItemLoc 
     (Qty, ITEM, Loc, Dt) 
VALUES (3, 'abc', 'L1', 1990), 
     (2, 'abc', 'L2', 1992), 
     (5, 'abc', 'L3', 2003), 
     (4, 'abc', 'LH', 2004), 
     (1, 'xyz', 'L4', 1990), 
     (2, 'xyz', 'L5', 1993), 
     (9, 'xyz', 'L6', 2001), 
     (2, 'xyz', 'LJ', 2004) ; 


/*looks complicated, and it is 
    I use a cte to try to ease it up a bit, 
    but I first identify a running sum of items 
    in the bins, and a pull order based on item 
    and year. 
*/ 


WITH cte 
      AS (SELECT a.Qty , 
         a.Item , 
         a.Loc , 
         a.Dt , 
         a.RunningSum , 
         a.PullOrder , 
         b.Qty AS OrderQty 
       FROM  (SELECT Qty , 
            Item , 
            Loc , 
            Dt , 
            RunningSum = (SELECT SUM(Qty) 
                FROM  @ItemLoc il1 
                WHERE il1.Item = il.Item 
                  AND il1.Dt <= il.Dt 
               ) , 
            PullOrder = ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Dt) 
          FROM  @ItemLoc il 
         ) a 
         JOIN (SELECT item , 
             MAX(qty) AS qty 
           FROM  @orders o 
           GROUP BY item 
          ) b ON a.Item = b.item 
      ) 
    /* I then use the cte to a) identify the minimum bin 
     which has a RunningSum of items greater than the OrderQty, 
     and b) pick all of the items in the bins below that, and 
     c) pick the remaining items from the last bin 
    */   


    SELECT Pick = CASE WHEN RunningSum <= OrderQty THEN Qty 
         ELSE OrderQty - (SELECT SUM(Qty) 
              FROM  cte c3 
              WHERE  c3.item = c1.ITem 
                AND c3.RunningSum < c1.RunningSum 
             ) 
        END , 
      c1.Item , 
      Loc 
    FROM cte c1 
      JOIN (SELECT Item , 
          MIN(PullOrder) AS po 
        FROM  cte c2 
        WHERE RunningSum >= OrderQty 
        GROUP BY Item 
       ) x ON c1.Item = x.Item 
         AND c1.PullOrder <= x.po 
+0

這看起來很棒!我會在幾分鐘後儘快檢查這個解決方案。謝謝! – Hatch 2009-10-28 15:01:43

0

重新審視這個問題後,我決定,這將是更爲有效的創建一個表值函數和

現在的查詢現在從1:45到0:03。真棒。

不幸的是,我不能張貼代碼,但對於解決一般的僞代碼爲:

創建表變量包含所有可以以任何方式依賴於一個開放的順序可挑位置。

創建第二個表變量以包含所有未結訂單。在每個訂單中包含您需要的任何列以顯示各個項目的狀態。

創建結果表(或者首先執行此操作,如果您使用的是表值函數),該表包含您挑選過程的必要信息。 (所以訂單號,項目#,什麼位置#你想讓它從拉。)

迭代:

從開放的訂單記錄數量的未結訂單表1,加入其中的位置數量> 0.將每個傳遞存儲到結果表中。

如果您有位置,請將剛剛插入結果表中的位置數量減1。 (有時一個訂單可能不是揀選因爲數量或orderstatus問題,但你仍然希望他們在結果報告或分配的目的。) :結束迭代

我感謝幫助斯圖爾特·安斯沃思,我只是想避免子查詢和東西。我設法寫這個,而不用多次連接到同一個表,也沒有子查詢。撞你的,因爲它的怪異真棒!