Sql语句,用于确定具有未结采购订单和销售订单的每个批次的可用数量

Sql语句,用于确定具有未结采购订单和销售订单的每个批次的可用数量,sql,Sql,我需要创建一个报告,按批号列出每种产品的可用数量。例如,我出售小部件A100。今天的日期是2014年2月11日,我手头上有两批小部件A100,分别是1001和1002。标段1001的现存量为100,而标段1002的现存量为200。我们有三个小部件A100 PO 1003、1004和1005的未结采购订单。PO1003数量为150,于2014年2月20日到期;PO 1004数量为200,于2014年2月27日到期。最后,采购订单1005的数量为250,应于2014年3月6日到期。因此,我们目前手头

我需要创建一个报告,按批号列出每种产品的可用数量。例如,我出售小部件A100。今天的日期是2014年2月11日,我手头上有两批小部件A100,分别是1001和1002。标段1001的现存量为100,而标段1002的现存量为200。我们有三个小部件A100 PO 1003、1004和1005的未结采购订单。PO1003数量为150,于2014年2月20日到期;PO 1004数量为200,于2014年2月27日到期。最后,采购订单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

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

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

如果您使用的是不同的数据库,则可以模拟以下逻辑:

Sub1块决定了在不考虑进货的情况下,承诺减少对手头的影响,并仅显示剩余的批次 Sub2块确定缺货订单对传入的影响,只返回第一个受影响的单据号,并显示其部分余额 Sub3块确定缺货订单减少对传入的影响,并仅返回步骤2中返回的SEBQUENT doc_no,逻辑上必须具有未受影响的余额 最后一步是合并结果,得到所需的3行 我确实做了一些假设,比如你的库存表上的批次目前在你的订单DTL上从来都不是单据号。根据您的应用程序实际存储数据的方式,如果我做了任何错误的假设,请告诉我,逻辑可能会交织在一起

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

你试过这个吗?我看不到任何代码。游标的一个替代方法是DO-WHILE循环。。。我很快就要挨揍了,因为我甚至提出了这个问题,但我个人倾向于尽可能地使用它而不是光标。您可以在这里使用sql fiddle上的查询和数据:
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