Sql Statement,用于确定每个批次的开放采购订单和销售订单的可用数量

时间:2014-02-11 23:06:40

标签: sql

我需要创建一个报告,按批号列出每个产品的可用数量。例如,我出售小部件A100。今天的日期是2014年11月2日,我手头有2个小部件A100(很多#1001和1002)。批次#1001的数量为100,而批次#1002的数量为200。我们有三个小工具A100的开放采购订单(PO#1003,1004和1005)。 PO#1003的数量为150,将于2014年2月20日到期,PO#1004的数量为200,将于2014年2月27日到期。最后,PO#1005的数量为250,并于2014年3月6日到期。因此,我们现有的现有数量为300,订购时为600。

假设我打开了四个销售订单(5001,5002,5003和5004)。销售订单5001为50,当前数量为50。销售订单5002为100,其数量为100。销售订单5003的数量为150,未提交,因为它不会在2014年2月24日之前发货。销售订单5004的数量为100,未提交,因为它不会在2014年3月3日之前发货。

现在,我需要根据上述和所有公开销售订单确定我可以出售的产品。

存储信息的表格如下(注意我已经简化了表格以便于沟通):

IN_INVENTORY
  ITEM_NO,
  QTY_AVAILABLE

PO_DTLS
  ITEM_NO,
  DUE_DATE,
  QTY_ORDERED

SO_DTLS
  ITEM_NO,
  SHIP_BY_DATE,
  QTY_COMMITTED,
  QTY_BACKORDERED

IN_INVENTORY
ITEM_NO LOT QTY
A100    1001    100
A100    1002    200

PO_DTLS
ITEM_NO DOC_NO  DUE_DATE    QTY
A100    1003    2/20/2014   150
A100    1004    2/27/2014   200
A100    1005    3/6/2014    250

SO_DTLS
ITEM_NO DOC_NO  SHIP_BY_DATE    QTY_COMMITTED   QTY_BACKORDERED
A100    5001    2/14/2014   50      0
A100    5002    2/16/2014   100     0
A100    5003    2/24/2014   0       150
A100    5004    3/3/2014    0       100


My expected output would look as follows:

ITEM_NO LOT QTY_AVAILABLE       AVAILABLE_DATE
A100    1002    50          2/11/2014
A100    1004    100         2/27/2014
A100    105 250         3/6/2014

我需要一个sql语句,根据列出的表和记录创建所需的输出。任何建议将不胜感激!!!我宁愿不使用光标,但是如果不编写应用程序就无法找到解决方法。

1 个答案:

答案 0 :(得分:0)

我使用Oracle完成了以下操作,并使用您的示例数据获得了您想要的结果。

如果您使用的是其他数据库,则可以模仿逻辑:

  1. Sub1区块确定对现有物品的影响(按承诺减少)而不考虑进货货物,并显示剩余余额的剩余货物
  2. Sub2块确定对传入内容的影响(减少延迟),并仅返回第一个受影响的doc_no,并显示其部分余额
  3. Sub3块确定对传入内容的影响(由延期交货减少),并仅返回后续doc_no(在步骤2中返回的值),逻辑上必须具有未受影响的余额
  4. 最后一步是合并结果,然后获得3行所需
  5. 我确实做了一些假设,例如你的IN_INVENTORY表上的批次目前从未在你的PO_DTLS上成为DOC_NO。根据应用程序实际存储数据的方式,如果我做了任何错误的假设,请告诉我,逻辑可能会被编织。

    with sub1 as
     (select x.item_no,
             x.lot,
             x.qty - y.going as qty_available,
             to_date('02/11/2014', 'MM/DD/YYYY') as available_date
        from in_inventory x
        join (select item_no, sum(qty_committed) as going
               from so_dtls
              where qty_committed > 0
              group by item_no) y
          on x.item_no = y.item_no
       where y.going < x.qty
       order by 1, 2),
    sub2 as
     (select item_no, doc_no, runner, due_date
        from ((select x.item_no,
                      x.doc_no,
                      x.qty,
                      y.going,
                      sum(x.qty - nvl(y.going, 0)) over(partition by x.item_no order by x.item_no, x.doc_no) as runner,
                      x.due_date
                 from po_dtls x
                 left join (select item_no, sum(qty_backordered) as going
                             from so_dtls
                            where qty_backordered > 0
                            group by item_no) y
                   on x.item_no = y.item_no
                  and x.doc_no = (select min(z.doc_no)
                                    from po_dtls z
                                   where z.item_no = x.item_no)
                order by 1, 2))),
    sub3 as
     (select item_no, doc_no, qty, due_date
        from ((select x.item_no,
                      x.doc_no,
                      x.qty,
                      y.going,
                      sum(x.qty - nvl(y.going, 0)) over(partition by x.item_no order by x.item_no, x.doc_no) as runner,
                      x.due_date
                 from po_dtls x
                 left join (select item_no, sum(qty_backordered) as going
                             from so_dtls
                            where qty_backordered > 0
                            group by item_no) y
                   on x.item_no = y.item_no
                  and x.doc_no > (select min(z.doc_no)
                                    from po_dtls z
                                   where z.item_no = x.item_no)
                order by 1, 2)))
    select *
      from sub1
    union
    select *
      from sub2
     where sub2.doc_no = (select min(x.doc_no) from sub2 x where x.runner >= 0)
    union all
    select *
      from sub3
     where sub3.doc_no > (select min(x.doc_no) from sub2 x where x.runner >= 0)
     order by item_no, lot