SQL根据列值指定连接行的数量

时间:2015-04-10 01:27:56

标签: sql sql-server-2008-r2

我有一个奇怪的要求。

说我有两张桌子:

ORDER_TB

  SEQ   PRODUCT_ID   ORDER_QTY  
   1        1            1
   2        1            1
   3        1            1


STOCK_TB
  LOCATION  STOCK_QTY
     A1        2
     B1        1


Desired Join Result:

PRODUCT_ID ORDER_QTY ASSIGNED_LOCATION
   1          1            A1
   1          1            A1
   1          1            B1

换句话说,我希望根据库存数量,在stock_tb中为每个产品分配一个位置。

这对我来说看起来不像是一套操作。是否可以使用连接或在解决此问题时是否还有其他干净的替代方案?

2 个答案:

答案 0 :(得分:0)

您需要做的是获取每列的累计总和 - 这为您提供每个值的第一个和最后一个订单。然后你可以在范围内进行连接。

with o as (
      select o.*, cumesum
      from ORDER_TB o OUTER APPLY
           (select sum(o2.order_qty) as cumesum
            from ORDER_TB o2
            where o2.seq <= o.seq
           ) o2
     ),
     s as (
      select s.*, s2.cumeqty
      from STOCK_TB s outer apply
           (select sum(s2.order_qty) as cumeqty
            from STOCK_TB
            where s2.location <= s.location
           ) s2
     )
select o.*, s.location
from o join
     s
     on o.cumesum between s.cumeqty - s.order_qty + 1 and s.cumeqty;

注意:这适用于您提供的数据。但是,如果两个表中的数量不对齐,则逻辑会更复杂。

答案 1 :(得分:0)

另一种方法是使用分析函数:

with cum as
 (select s.*, sum(stock_qty) over(order by location) as cum_qty
    from stock_tb s)
select x.product_id, x.order_qty, y.location as assigned_location
  from (select o.*,
               row_number() over(partition by product_id order by seq) as curr_qty
          from order_tb o) x
 cross join cum y
 where y.cum_qty =
       (select min(z.cum_qty) from cum z where z.cum_qty >= x.curr_qty)
    or (not exists (select 1 from cum z where z.cum_qty > x.curr_qty) and
        y.cum_qty = x.curr_qty)
 order by seq

小提琴: http://sqlfiddle.com/#!6/e41b0/1/0