Oracle数据分摊问题解析

常会碰到由于业务需要,需要将某种汇总的数据按照一定的原则分摊给一堆数据。 其实,如果逻辑清晰的话,这类型的程序还是比较好些的。 本文重点是如果用简单的程序实现这种效果,而且不容易分摊分错。 所有的分摊问题,首先必须要搞清楚以下几点问题: 1

经常会碰到,由于业务需要,需要将某种汇总的数据按照一定的原则分摊给一堆数据。
其实,如果逻辑清晰的话,这类型的程序还是比较好些的。
本文重点是如果用简单的程序实现这种效果,而且不容易分摊分错。

所有的分摊问题,首先必须要搞清楚以下几点问题:
1 首要的,要确定 什么东西,多少数量 分摊给什么东西?举个形象的例子,一桶沙子分摊给一些瓶子。
2 分摊的先后原则。上面的例子,一桶沙子分摊给一些瓶子,那瓶子的被分摊顺序是什么样子的?沙子先给哪个瓶子?要先确定清楚。

说得好像有点麻烦,举个例子说明。
最近接到的一个需求:
PO入库的时候,批次可能重复输入,所以入库之后,库存已经汇总在一起了。然后用户对(汇总的)库存进行消耗(就是杂发)。
现在需要有个报表可以知道:按照先进先出的原则,区分用户的一段期间内的消耗数量 对应的是那笔入库单号。

备注:假设下面的数量对应都是主单位。

7.1 入库单R1  料号A 批次P1 接收入库 400
7.3 入库单R2  料号A 批次P1 接收入库 300
这时候,P1批次库存共 700
——-消耗(杂发)明细
7.10 消耗P1 100
7.12 消耗P1 200
8.10 消耗P1 200
8.13 消耗P1 100
8.20 消耗P1 50
9.20 消耗P1 50

如果查询报表的日期选择的是:8.1~8.31
     8.1号 之前共消耗100+200=300
8.1~8.31号 之内一共消耗:200+100+50=350

所以核心问题是要将350如何分摊在R1和R2里面。
要实现的分摊效果:
      入库总数      之前消耗的分摊    期间内消耗的分摊
R1       400           300                  100
R2       300            0                   250

所以,结果是,报表是:8.1~8.31
一共消耗350,对应入库单的消耗情况:
R1消耗100
R2消耗250

实现逻辑:
你可以假想,现在有2个沙桶,
红色的沙桶装的沙子是 之前消耗的分摊 的数量
黑色的沙桶装的沙子是 期间内消耗的分摊 的数量
每张入库单就是一个瓶子,所以共有2个瓶子,R1和R2。现在是如何将 红色的沙子 和 黑色的沙子 装到这2个瓶子里面。

装沙规则:
1 用沙子的顺序:先用 红色的沙子,用完之后,再用黑色的沙子。
2 装瓶子的顺序:按照先进先出的原则,必须先装瓶子R1,再装R2.

DECLARE
  L_PRE_PERIOD_QTY NUMBER; —期间前的汇总消耗量 —之前消耗的分摊 的数量—红色的沙子
  L_CURR_PERIOD_QTY NUMBER ; –本期的汇总消耗量–期间内消耗的分摊 的数量—黑色的沙子
  —-装的结果用记录类型存下来,因为后面要用到。
   TYPE shipment_consume_Rec_Type   IS RECORD
   (
     SHIPMENT_LINE_ID  NUMBER
   , PRIMARY_QUANTITY             NUMBER
   , consume_pre_qty NUMBER
   , consume_curr_qty NUMBER
      );
    TYPE shipment_consume_Tbl_Type IS TABLE OF shipment_consume_Rec_Type
    INDEX BY BINARY_INTEGER ;
    L_shipment_consume_Tbl shipment_consume_Tbl_Type;
    N NUMBER;
BEGIN
  —-1 首先要算出红色的沙子和黑色的沙子的总数量,就是有多少数量可分摊。
SELECT nvl(sum(case when MMT.transaction_date      ABS(NVL(MTLN.PRIMARY_QUANTITY,0))
     else
       0
     end ),0) PRE_PERIOD_QTY,
     nvl(sum(case when MMT.transaction_date >= :P_F_START_DATE then
     ABS(NVL(MTLN.PRIMARY_QUANTITY,0))
     else
       0
     end ),0) CURR_PERIOD_QTY
   INTO L_PRE_PERIOD_QTY,L_CURR_PERIOD_QTY
  FROM MTL_MATERIAL_TRANSACTIONS MMT
      ,MTL_TRANSACTION_LOT_NUMBERS MTLN
WHERE MMT.TRANSACTION_ID = MTLN.TRANSACTION_ID
   AND MMT.TRANSACTION_TYPE_ID = 74
   AND MMT.TRANSACTION_ACTION_ID = 6
   AND MMT.OWNING_TP_TYPE = 1 —所有权转出的(寄售供应商的库存)
   —
   AND MMT.ORGANIZATION_ID = 103
   AND MMT.INVENTORY_ITEM_ID = 11783561
   AND MTLN.LOT_NUMBER = ‘P0000001’
   AND MMT.transaction_date   DBMS_OUTPUT.PUT_LINE(‘L_PRE_PERIOD_QTY:’||L_PRE_PERIOD_QTY||’ -L_CURR_PERIOD_QTY:’||L_CURR_PERIOD_QTY);
   N := 1;

   —–2 分摊主逻辑。
   FOR REC_SHIPMENT_LINE IN (
       —–瓶子(入库单)的游标
    SELECT MMT.ORGANIZATION_ID
        ,MMT.INVENTORY_ITEM_ID
        ,MTLN.LOT_NUMBER
        ,MTLN.TRANSACTION_DATE
        ,RT.SHIPMENT_HEADER_ID
        ,RT.SHIPMENT_LINE_ID
        ,MTLN.PRIMARY_QUANTITY
    FROM MTL_TRANSACTION_LOT_NUMBERS MTLN, MTL_MATERIAL_TRANSACTIONS MMT,RCV_TRANSACTIONS RT
   WHERE MTLN.TRANSACTION_ID = MMT.TRANSACTION_ID
     AND RT.TRANSACTION_ID = MMT.RCV_TRANSACTION_ID
     AND MMT.TRANSACTION_TYPE_ID = 18
     AND MMT.TRANSACTION_SOURCE_TYPE_ID = 1
     AND XYG_PO_PKG.CHECK_PO_LINE_CONSIGN(RT.PO_LINE_ID) = ‘Y’
     AND MMT.ORGANIZATION_ID = 103
     AND MMT.INVENTORY_ITEM_ID = 11783561
     AND MTLN.LOT_NUMBER = ‘P0000001’
     ORDER BY MTLN.TRANSACTION_DATE,MMT.TRANSACTION_ID) LOOP
       —2.1 优先消耗期初之前的耗料数量,就是先用红色的沙子的数量。
       IF L_PRE_PERIOD_QTY >= REC_SHIPMENT_LINE.PRIMARY_QUANTITY THEN —当红色沙子的数量大于瓶子的容量的时候。
         L_shipment_consume_Tbl(N).SHIPMENT_LINE_ID :=REC_SHIPMENT_LINE.SHIPMENT_LINE_ID;
         L_shipment_consume_Tbl(N).PRIMARY_QUANTITY :=REC_SHIPMENT_LINE.PRIMARY_QUANTITY;
         —-消耗红沙的数量就是瓶子的容量。
         L_shipment_consume_Tbl(N).consume_pre_qty :=REC_SHIPMENT_LINE.PRIMARY_QUANTITY;
         L_shipment_consume_Tbl(N).consume_curr_qty :=0;
         —-期初数量就是剩下要分配的数量。因为红色沙子已经被消耗掉一部分了。
         L_PRE_PERIOD_QTY :=L_PRE_PERIOD_QTY-REC_SHIPMENT_LINE.PRIMARY_QUANTITY;
       ELSE —当红色沙子的数量小于瓶子容量的时候
         L_shipment_consume_Tbl(N).SHIPMENT_LINE_ID :=REC_SHIPMENT_LINE.SHIPMENT_LINE_ID;
         L_shipment_consume_Tbl(N).PRIMARY_QUANTITY :=REC_SHIPMENT_LINE.PRIMARY_QUANTITY;
         —-瓶子装 红色沙子的数量就是红色沙子的数量了
         L_shipment_consume_Tbl(N).consume_pre_qty :=L_PRE_PERIOD_QTY;

         —-这时候已经用完红色沙子了,开始用黑色沙子了—–
           —2.2 当黑色沙子数量大于瓶子 可用的容量 的时候。
         IF L_CURR_PERIOD_QTY > (REC_SHIPMENT_LINE.PRIMARY_QUANTITY – L_PRE_PERIOD_QTY) THEN
           —该瓶子 装黑色沙子的数量 就是 瓶子的可用容量。
           L_shipment_consume_Tbl(N).consume_curr_qty := REC_SHIPMENT_LINE.PRIMARY_QUANTITY – L_PRE_PERIOD_QTY;
           —本次还有多少数量需要被下一个单号分摊,就是确定剩下还有多少黑色沙子可用。
           L_CURR_PERIOD_QTY := L_CURR_PERIOD_QTY – L_shipment_consume_Tbl(N).consume_curr_qty;
         ELSE
           —-当黑色沙子数量 小于或者等于 瓶子的可用容量的时候
           —–该瓶子装黑色沙子的数量就是 瓶子的可用容量。
           L_shipment_consume_Tbl(N).consume_curr_qty := L_CURR_PERIOD_QTY;
           —–黑色沙子用完咯!~~一定要赋值0,因为根据黑色沙子的使用情况判断后面是否要退出瓶子的循环。
           L_CURR_PERIOD_QTY := 0;
         END IF;
         L_PRE_PERIOD_QTY:= 0;
       END IF;
        N := N+1;
        —-当黑色沙子用完的时候,要退出循环。因为沙子数量可能很少,但是瓶子很多。。。没必要再循环下去了。
        IF L_CURR_PERIOD_QTY          EXIT;
        END IF;
     END LOOP;
    
     —显示装的结果。
     FOR I IN 1..L_shipment_consume_Tbl.COUNT LOOP
      DBMS_OUTPUT.PUT_LINE(L_shipment_consume_Tbl(I).SHIPMENT_LINE_ID
      ||’-‘|| L_shipment_consume_Tbl(I).PRIMARY_QUANTITY
      ||’-‘|| L_shipment_consume_Tbl(I).consume_pre_qty
      ||’-‘|| L_shipment_consume_Tbl(I).consume_curr_qty
      );
     
     END LOOP;
END;

/*
—例如:
L_PRE_PERIOD_QTY:0 -L_CURR_PERIOD_QTY:2020.2
18467366-1605.5-0-1605.5
18633076-5014.7-0-414.7

*/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1082838.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月2日 19:59:17
下一篇 2025年12月2日 19:59:38

相关推荐

  • 深入学习响应式布局框架:适合初学者到专家的详尽指南

    响应式布局框架解析:从初学者到专家的必备指南 随着移动设备的普及和多样化,响应式布局成为了现代Web设计的必备技能。响应式布局框架以其简单、灵活和可维护的特点,成为了开发者们的首选工具。然而,对于初学者来说,学习和理解响应式布局框架可能会感到有些困惑。本文将从初学者到专家,为您提供一个详细的指南,帮…

    2025年12月24日
    000
  • 揭秘静态定位的不同类型:揭示常见的静态定位类型详解

    静态定位类型大揭秘:解析常见的静态定位类型有哪些 引言: 随着移动互联网和定位技术的迅速发展,静态定位在现代生活中扮演了重要的角色。静态定位是指通过对目标物体或者人体的位置信息进行测量和计算,来确定其准确位置的技术。它在导航、地图应用、智能交通系统等方面具有广泛的应用。本文将为大家揭秘常见的静态定位…

    2025年12月24日
    000
  • 优化CSS解析过程中的回流和重绘技巧

    CSS回流和重绘解析及优化技巧 近年来,网页性能优化成为了前端开发中的重要环节,其中包括对CSS回流和重绘的解析及优化。在优化CSS的过程中,我们需要了解回流和重绘的定义,并学习一些具体的优化技巧。 什么是回流和重绘? 回流(reflow)和重绘(repaint)是浏览器渲染引擎对网页进行布局和绘制…

    2025年12月24日
    000
  • 探秘五种流行的CSS布局框架

    CSS布局框架大揭秘:五种流行框架解析 引言:在网页设计和开发过程中,如何实现良好的布局一直是一个重要的挑战。CSS布局框架通过提供强大的工具和组件,帮助我们更轻松地创建复杂的布局,提高开发效率。在本文中,我们将探讨五种流行的CSS布局框架,并提供具体的代码示例。 一、BootstrapBootst…

    2025年12月24日 好文分享
    000
  • 深入了解五种常见的CSS布局框架解析

    了解CSS布局框架:五种常见布局解析 在网页设计与开发中,CSS布局是一个非常重要的方面。一个好的布局可以使网页更加美观、功能更加完善。而了解CSS布局框架的知识,则能够帮助我们更好地掌握网页的布局技巧。本文将介绍五种常见的CSS布局,并提供具体的代码示例。 一、流式布局(流式定位) 流式布局是一种…

    2025年12月24日
    000
  • 揭秘CSS框架:常见框架解析及特点研究

    CSS框架大揭秘:解析常见的几种框架及其特点,需要具体代码示例 引言:在现代网页设计中,CSS框架扮演着重要的角色,它们能够极大地简化我们的开发工作,提高开发效率。本文将深入解析常见的几种CSS框架,并提供详细的代码示例,帮助读者更好地理解和应用这些框架。 一、Bootstrap:Bootstrap…

    2025年12月24日
    000
  • 解析CSS伪类和伪元素的常见用法和实例

    深入探讨CSS伪类和伪元素的常见用法和实例解析 在前端开发中,CSS是我们常用的样式设计语言之一。除了基本的选择器和属性,CSS还提供了一些特殊的选择器,称为伪类和伪元素。本文将深入探讨CSS伪类和伪元素的常见用法和实例解析,并附上具体的代码示例。 一、伪类的常见用法和实例解析 :hover伪类 :…

    2025年12月24日
    000
  • CSS3的学习轨迹和常见误区解析

    CSS3的学习轨迹和常见误区解析 引言:随着Web技术的不断发展,CSS3已经成为了前端工程师必备的技能之一。通过掌握CSS3的各种功能和特效,我们能够创建出更加丰富多彩的网页布局和交互效果。本文将介绍CSS3的学习轨迹,同时分析一些常见的误区,并提供一些代码示例。 一、学习轨迹: 1.掌握基本语法…

    2025年12月24日
    000
  • canvas线条的属性解析

    本文主要和大家介绍了canvas线条的属性详解的相关资料,小编觉得挺不错的,现在分享给大家,希望能帮助到大家。 一、线条的帽子lineCap 取值:butt(默认值),round圆头,square方头 var canvas=document.getElementById(“canvas”);canv…

    2025年12月24日 好文分享
    000
  • 浅谈css网页的布局问题

    这次给大家带来浅谈css网页的布局问题,css网页的布局问题的注意事项有哪些,下面就是实战案例,一起来看一下。 1、左边固定,右边自适应布局的两种实现方式 效果图如下: 大屏展示: 小屏展示:   第一种实现方式通过负边距与浮动 实现左边固定,右边自适应的布局。 主要代码如下: .left{floa…

    2025年12月24日 好文分享
    000
  • 对CSS继承的深度解析

      我酷爱模块化设计。长期以来我都热衷于将网站分离成组件,而不是页面,并且动态地将那些组件合并到界面上。这种做法灵活,高效并且易维护。   但是我不想我的设计看上去是由一些不相关的东西组成的。我是在创造一个界面,而不是一张超现实主义的照片。   很幸运的是,已经有一项叫做 CSS 的技术,就是特意设…

    2025年12月23日
    000
  • 解析CSS3中nth-child与nth-of-type的区别

    css3中nth-child与nth-of-type的区别其实很简单::nth-of-type为什么要叫:nth-of-type?因为它是以”type”来区分的。也就是说:ele:nth-of-type(n)是指父元素下第n个ele元素, 而ele:nth-child(n)是…

    2025年12月23日 好文分享
    000
  • java怎么编译运行.html_java编译运行.html方法【教程】

    Java程序的编译运行与HTML无关,需使用JDK。1. 编写HelloWorld.java文件;2. 命令行执行javac HelloWorld.java生成.class文件;3. 执行java HelloWorld运行程序。注意:HTML是网页标记语言,不能直接运行Java代码,勿将二者混淆。确…

    2025年12月23日
    000
  • html文档中含有java怎么运行_html含java运行方法【教程】

    现代浏览器不支持Java Applet,推荐通过JavaScript调用Java后端服务或使用WebAssembly运行Java代码。 如果您在HTML文档中嵌入了Java代码,但发现无法正常运行,这通常是因为现代浏览器不再支持Java小程序(Applet)或相关插件。以下是几种实现HTML中Jav…

    2025年12月23日
    000
  • 怎么运行html的applet小程序_运行html applet小程序步骤【指南】

    现代浏览器已不再默认支持Java Applet,需通过安装JRE、启用插件、使用支持NPAPI的旧版浏览器(如Firefox 52.9 ESR)、调整Java安全级别至中,并将网站添加到例外站点列表方可运行。 如果您在尝试运行HTML中的Applet小程序时遇到问题,可能是因为现代浏览器已不再默认支…

    2025年12月23日
    000
  • 动态生成HTML表格:优化JavaScript数据展示与导出

    本文旨在解决JavaScript中动态生成HTML表格时遇到的代码冗余和样式控制难题。通过引入数据驱动的编程思想,我们将数据与视图逻辑分离,首先将表格内容组织为JavaScript对象数组,然后利用一个通用的函数将这些结构化数据渲染为可读性强、易于维护且支持灵活样式的HTML表格字符串。这种方法不仅…

    2025年12月23日
    000
  • HTML5性能优化怎么实现_HTML5新特性在性能优化方面的应用方法

    HTML5通过语义化标签、Web Storage、Canvas/SVG、Service Worker和原生媒体支持等技术提升性能:1. 语义化标签优化渲染效率;2. Web Storage减少网络请求;3. Canvas/SVG降低资源加载量;4. Service Worker实现离线缓存;5. 原…

    2025年12月23日
    000
  • 利用UTM参数与GTM优化链接点击来源追踪

    本文详细阐述了如何通过UTM参数精准追踪营销链接的点击来源,并深入探讨了Google Tag Manager (GTM) 在此过程中的高级应用。文章首先介绍了UTM参数的构成、生成方法及其在Google Analytics中的自动解析机制,强调其在识别流量来源方面的核心作用。随后,探讨了GTM如何通…

    2025年12月23日
    000
  • 使用BeautifulSoup和JSON有效抓取动态加载的网页表格数据

    本教程旨在解决使用BeautifulSoup抓取网页表格时,因数据动态加载导致部分内容缺失的问题。通过分析网页背后的API请求,直接获取并解析JSON数据源,再结合BeautifulSoup提取的HTML结构信息,最终实现完整且准确的数据抓取。文章将提供详细的代码示例和实现步骤。 理解网页动态内容与…

    2025年12月23日
    400
  • 解决BeautifulSoup爬取网页表格中动态内容缺失问题

    本文旨在解决使用BeautifulSoup爬取网页表格时,因部分数据通过JavaScript动态加载导致内容缺失的问题。通过详细分析Oracle云定价页面的案例,教程将指导读者如何识别并获取隐藏在JSON API中的动态数据,并将其与BeautifulSoup解析的静态HTML内容有效整合,最终构建…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信