首页 »
资源 » 此处
在 Envision 中最常用的创建表的方式就是读取平面文件中的表。但是,Envision 也提供了创建表的功能。这些表可以在脚本中定义和例示。对于任何一种输入表都不具备特定计算所需属性的情形,创建表非常有用。
语法概述
创建表的常用语法蕴含在
table
和
extend
声明中,此类声明中附带语法:
table T = extend.range(Orders.42)
此处的关键字
table
不能与
show table
中的磁贴类型相混淆。之后便可以像从文件中加载的任何普通表一样,来在脚本中使用表
T
。
show table "Number of lines" with sum(T.1)
extend.range()
最简单的创建表的方式是使用范围扩展
extend.range()
:对于原始表中的每一行,会创建 N 行并进行编号。范围扩展对于在表中引入新行的情况很有用。
语法如下:
table T = extend.range(Orders.K)
T.Quantity = Orders.Quantity // implicit projection
show table "Line numbers" with T.N, T.Quantity
其参数应为整数,原始表中的上一行与下一行的数值是不同的。这样便可以控制所要引入的行数的粒度。
表
T
作为最初以参数形式传递的表的扩展来键入。因此,从上面的第 2 行可以看出,纯交叉表分配也是可行的,因为
T
中的每一行仍与
Orders
中的原始对应部分相关联。
T.N
字段默认为已填充,该字段表示行数,从 1 开始,并按增量 +1 递增。
请注意,函数
extend.range()
可以生成任意多的行数。但首先, 生成大表可能会很慢;其次,根据您 Lokad 帐户中的配额,这个过程可能不会成功。实际上,如果
K
比平均数大 10,那么
extend.range()
可能就不是您所解决的问题的正确方法。
extend.distrib()
Envision 分布提供了强大的代数运算,借助这种运算可以不用对列表进行进行令人费解的概率计算。但是,有时原始概率列表也是可以的并且甚至是很可取的。而分布扩展
extend.distrib()
将分布向量转变成了一个表,语法如下:
table T = extend.distrib(D)
show table "Distribution details" with Id, T.Min, T.Max, T.Probability
参数
D
的预期输入为分布向量,此类向量通常由 Lokad 的概率预测引擎生成。表
T
作为原始表(即上面这段脚本中的隐式
Items
表)的扩展键入。表
T
中填充了这三个字段:
T.Min
:此段的整数下限(包含在内)T.Max
:此段的整数上限(包含在内)T.Probability
:所含范围的分布之和
虽然字段的名称为
Probability
,但返回的其实是桶范围内的分布之和。
对于相对紧凑的分布,段的长度为 1,因此
T.Min == T.Max
。但是,如果分布延续到更大的值,长度为 1 的段可能会产生数百万行,因而变得无法管理。所以,在面对较大值的分布时,Envision 会自动围绕较大的段来聚合分布。相关算法会进行调整,以保持所生成表的大小可以管理。
按照设计,
extend.distrib()
总是会选出长度为 0 的段。因此,段 [0;0] 总是在生成的表中得到其自身的行。这种行为对于许多边缘案例中需求为 0 的业务情形(例如无限的存货保证期)其实很有帮助,这种情况下需要采用某些专用的逻辑。
此外还针对
extend.distrib()
提供了三个过度加载,目的是对所生成表的具体粒度进行进一步控制。
差距
第一个过度加载的用意,是在考虑当前库存水平时帮助构建采购优先级列表。其语法如下:
table T = extend.distrib(D, S)
第一个参数
D
的定义如上所示。第二个参数
S
的输入应为整数。在提供有第二个参数的情况下,所生成的表总是包含两行,这两行专门用于 [0;0] 和 [1;S] 这两个段。其他段则是自动生成,并从 S+1 开始,上面进行了详细说明。此参数未指定时的默认值为 0。
参数
S
通常定义为可用存货与订购存货之和。在进行再订货时,实际上只会考虑超出当前库存水平的需求概率。
倍数
第二个过载面向涉及
批次倍数的情形。在这些情形中,此表应当对特定大小的段进行迭代。其语法如下:
table T = extend.distrib(D, S, M)
参数
D
和
S
的定义如上所示。第三个参数
L
的输入应为整数。它表示所需的段长。因此,此表包含段 [0;0], [1;S], [S+1;S+M] [S+M+1;S+2M] … 的列表。如果
L
为 0,则此函数会回到自动调整段大小的状态。
强制段长为 1 可能会导致性能问题,因为表的大小可能会任意大。因此,Envision 可以退而求其次,即改为使用一个叫做
M
的
倍数。通过使用倍数,可以确保
批次倍数逻辑正常工作;同时又能对所生成的行数施加同样的限制。
根据经验,我们建议不要使用这种过载,除非是涉及到批次倍数;当涉及批次倍数时,建议将所有不具备特定批次倍数的项目的
M} 保持为 0。
达到特定值
第三个过载针对涉及MOQ的情形。在这些情形中,表应当进行足够长的迭代,以便达到所需的特定值。相关语法为:
table T = extend.distrib(D, S, M, R)
上面定义了参数 D
、S
和 M
。第四个参数 R
应为非负整数。它表示网格所要达到的最大值,也即在某一行中,T.Max
要大于或等于 R
。未指定此参数时,其默认值为 0。
实际上,此参数用于处理较大的最小订单量 (MOQ) 限制,而这一点只有在生成的表进行足够长的迭代从而覆盖 MOQ 值时才回满足。
根据经验,我们建议不要使用此过载,除非是要达到 MOQ;在涉及 MOQ 时,建议 R
尽量小。较小的 R
值不会阻止表 T
达到较高的值,只会确保达到较大的值。
extend.billOfMaterials()
物料清单涉及到关注点不在所售或所服务的项目上,而在于其部件或组成的情形。对于这些情形,最好将“项目”级别的需求历史记录转换为“部件”级别的需求历史记录。转换过程由指定各个项目组成的物料清单来控制。
调用函数 extend.billOfMaterials()
精准地涵盖了这种使用情况,如下所示:
table T = extend.billOfMaterials(
Item: J.Id
Part: B.PartId
Quantity: B.Quantity
DemandId: O.OrderId
DemandValue: O.Quantity)
T.DemandDate by T.DemandId = same(O.Date) by O.OrderId // illustrate how to get the date
show table "Details" with Id, T.DemandDate, T.Quantity
应当有 J
、B
和 O
这三个表。表 J
通常为项目表,但这一点并非硬性规定。表 B
拟作为物料清单表;其预期输入应为表 J
的扩展,即 J
刚好为项目表时,其类型为 (Id, *)
。表 O
预计为需求历史记录,通常为订单表。表 O
也应为表 J
的扩展。
最后得到的表就是表 J
的扩展,其中存在适当的仿射性。表 T
包含两个字段,其中已填充如下值:
T.DemandId
,用于在表 T
中提供一种识别表 O
中原始行的方式。T.Quantity
,此值通过转出物料清单获取。
将日期注入表 T
常常比较有用。这个过程可以通过 left-by 语句来完成,如上文 billOfMaterials()
块下面的行所示。
函数 extend.billOfMaterials()
支持递归部件,即一个项目既可以在表 B
中作为组件出现,也可以作为捆绑包出现。如果在物料清单表中发现循环相关性,该函数自然会失败。
参数 Quantity
表示 B.PartId
的单元数。在销售或维修标示有 {{J.Id
的部件时,会涉及到这一点。