2009-10-23 56 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问题,但你仍然希望他们在结果报告或分配的目的。) :结束迭代

我感谢帮助斯图尔特·安斯沃思,我只是想避免子查询和东西。我设法写这个,而不用多次连接到同一个表,也没有子查询。撞你的,因为它的怪异真棒!