• SqlServer function 函数


    SqlServer的数据库Tsql还是很强大,以此来纪念下表值函数的语法吧。

      1 -- =============================================
      2 -- Author:        <jonney>
      3 -- Create date: <2018.07.01>
      4 -- Description:    <根据产能、单机用料比例、班次、配送频率、提前期、最小包装数、欠品数、余料,等因素按时间点把料配送到产线>
      5 -- =============================================
      6 ALTER FUNCTION [dbo].[KittingItemCycleFn] 
      7 (
      8     -- Add the parameters for the function here
      9     @pWorkshop varchar(50) = '',-- 车间
     10     @pDateStart varchar(50) = '',-- 计划开始日,开始
     11     @pDateEnd varchar(50) = '',-- 计划开始日,结束
     12     @pParentItem varchar(50) = '',-- 制品号
     13     @pJon varchar(50) = '',-- Jon
     14     @pWorkOrderNo varchar(50) = ''-- 工单号
     15 )
     16 RETURNS 
     17 @result TABLE 
     18 (
     19     [Id] [int] NULL,
     20     [WorkOrderNo] [varchar](50) NULL,
     21     [ParentItem] [varchar](50) NULL,
     22     [Jon] [varchar](50) NULL,
     23     [Workshop] [varchar](50) NULL,
     24     [StartDate] [varchar](50) NULL,
     25     [CycleTime] [int] NULL,
     26     [ItemNo] [varchar](50) NULL,
     27     [Qty] [decimal](10, 2) NULL,
     28     [QtyQp] [decimal](10, 2) NULL,
     29     [ExtrNo] [varchar](50) NULL,
     30     [Whs] [varchar](50) NULL,
     31     [Keeper] [varchar](50) NULL
     32 )
     33 AS
     34 BEGIN
     35     -- Fill the table variable with the rows for your result set
     36     
     37     -- 若计划开始日期,开始为空,设置为今天
     38     if (@pDateStart = '')
     39     begin
     40       set @pDateStart = DATEADD(DD, -1, GETDATE());
     41     end;
     42 
     43     -- 若计划开始日期,结束为空,设置为明天
     44     if (@pDateEnd = '')
     45     begin
     46       set @pDateEnd = DATEADD(DD, 1, GETDATE());
     47     end;
     48     
     49     -- 声明返回的结果集
     50     --declare @result dbo.KittingItem, @id int = 0;
     51     declare @id int = 0;
     52 
     53     -- 声明一个游标,获取配料出库=6的出库单明细
     54     /*
     55       出库单据 = [SHLL]表
     56           DSRD = 0 = 未作废
     57           TYPE = 901 = 正常出库
     58           [DESC] = 6 = JON配料出库
     59     */
     60     declare kitItemRow cursor for
     61     select b.ID, a.NO WorkOrderNo, a.ParentItem, a.Jon, a.Workshop, a.ExpectDate WorkStartDate, c.CODE ItemNo, b.ORDQ Qty, f.START_TIME, f.REQ_TYPE, f.QTY, f.XFER_NO
     62            , g.CODE Whs, (select top 1 w.LBL from IUW z inner join [USER] w on z.USR=w.ID where z.DSRD=0 and z.WHS=a.WHS and z.ITM=b.ITM) Keeper
     63     from [dbo].[SHPL] a inner join [dbo].[SHLL] b on a.ID = b.SHLO 
     64                         inner join ITEM c on b.ITM = c.ID
     65                         inner join EREF d on b.ID = d.SHPL
     66                         inner join EXTR f on d.EXTR = f.XFER_NO
     67                         left join  WRHS g on a.WHS = g.ID
     68     where a.DSRD = 0 and a.TYPE=901 and a.[DESC]=6 and a.Workshop = @pWorkshop and a.ExpectDate between @pDateStart and @pDateEnd
     69           and (@pParentItem = '' or a.ParentItem=@pParentItem)
     70           and (@pJon = '' or charindex(@pJon, a.Jon) > 0) 
     71           and (@pWorkOrderNo = '' or a.NO = @pWorkOrderNo)
     72     order by f.REQ_TYPE;
     73     
     74     -- 打开游标
     75     open kitItemRow;
     76 
     77     -- 声明行变量,用于处理业务逻辑
     78     declare @rId bigint, @rWorkOrderNo varchar(50), @rParentItem varchar(50), @rJon varchar(50), @rWorkshop varchar(50)
     79             , @rWorkStartDate datetime, @rItemNo varchar(50), @rQty decimal(10, 2), @rWhs varchar(50), @rKeeper varchar(50);
     80 
     81     -- Imaps 数据信息
     82     declare @shiftStart int, @reqType varchar(10), @qty decimal(10, 2), @extrNo varchar(50);
     83 
     84     -- 游标移动到下一行
     85     fetch next from kitItemRow into @rId, @rWorkOrderNo, @rParentItem, @rJon, @rWorkshop, @rWorkStartDate, @rItemNo, @rQty, @shiftStart, @reqType, @qty , @extrNo, @rWhs, @rKeeper;
     86 
     87     -- 若移动游标后有数据,一直循环读取
     88     WHILE (@@FETCH_STATUS =0)
     89     begin
     90         -- 班次特殊处理
     91         set @shiftStart = @shiftStart / 100 -1;
     92 
     93         -- 对欠品的特殊处理
     94         if @reqType = '95' or @reqType = '99'
     95         begin
     96           set @rQty = @qty; -- 将总的分配数量设置为欠品
     97         end
     98         
     99         -- 获取部品的Cycle策略,若发货频率不等于0,则按照时间别(TYPE = 1602)配料
    100         declare @moq int=0, @freq int=0, @preDeli int=0;-- 最小包装单位
    101         select @moq=a.PARM1, @freq=a.PARM2, @preDeli=a.PARM3 from STRG a inner join ITEM b on a.ITM = b.ID where a.DSRD=0 and a.TYPE = 1602 and b.CODE = @rItemNo;
    102         if @preDeli is not null -- 如果没有设置提前时间,则不考虑
    103         begin
    104           set @shiftStart -= @preDeli; -- 减掉提前发货小时
    105         end;
    106         
    107         -- 声明 制品的满班产量、部品的单机用量
    108         declare @cap int=0, @usage int=0;
    109         select @usage=PARM1 from JITM where DSRD=0 and TYPE=2202 and MCHC = @rParentItem and ITMC= @rItemNo;-- 获取部品的单机用量TYPE=2202
    110         select @cap=PARM1 from JITM where DSRD=0 and TYPE=2201 and MCHC = @rParentItem;-- 获取制品的满班产量TYPE=2201
    111         
    112         declare @capItem int = @rQty;-- 当前部品的应发数量
    113         declare @sendTimes int = 1; -- 发货次数
    114         declare @itemSendQty int = @capItem / @sendTimes; -- 当前部品每次发货XX件
    115 
    116         -- 发货频率、满班产量、单机用量都设置过,才考虑满班产量
    117         if (@cap > 0 and @usage > 0 and @freq > 0)
    118         begin
    119           set @capItem = @cap * @usage;-- 当前部品的满班用量
    120           set @sendTimes = 8 / @freq; -- 重新设置发货频率
    121           set @itemSendQty = @capItem / @sendTimes; -- 当前部品每次发货XX件
    122         end
    123         else if (@freq > 0) -- 如果只设置了发货频率,那就只按照8除以发货频率来计算
    124         begin
    125           set @capItem = @rQty;
    126           set @sendTimes = 8 / @freq; -- 重新设置发货频率
    127           set @itemSendQty = @capItem / @sendTimes; -- 当前部品每次发货XX件
    128         end
    129         else -- 否则就按照集约类型,一次发完
    130         begin 
    131           set @sendTimes = 1; -- 重新设置发货频率
    132           set @itemSendQty = @rQty; -- 一次都发完
    133         end
    134         
    135         -- 设置最迟配送时间
    136         declare @lastTime int = @shiftStart + (@sendTimes - 1)*@freq;
    137         -- 记录标准配送数量,有可能一次配送量超过标准的两次、多次
    138         declare @standQty int = @itemSendQty;
    139         -- 记录第几次配送
    140         declare @curTime int=0;
    141 
    142         -- 判断最小包装数@moq
    143         declare @modQty int=0;
    144         if (@moq > 0)
    145         begin
    146           set @modQty = @itemSendQty % @moq;
    147           if(@modQty > 0)
    148           begin
    149             set @itemSendQty = (@itemSendQty / @moq + 1) * @moq;
    150           end            
    151         end
    152 
    153         -- 计算余料,放在第一次配送
    154         declare @yuLiao int = 0;
    155         set @yuLiao = @rQty - @itemSendQty * @sendTimes;
    156 
    157         -- 该行是否已经读取过欠品数据
    158         declare @yijing int = 0;
    159         declare @mpqQty int = @itemSendQty; -- 考虑过最小包装后的一次配送数
    160         
    161         -- 以下处理配料情况,即Qty > 0
    162           while @rQty > 0
    163           begin
    164             set @id += 1;--结果行号自增
    165             set @curTime += 1;
    166             set @rQty -= @itemSendQty;
    167 
    168             -- 若是第一次配料,且存在余料,就放在第一次配送
    169             if(@yuLiao >0 and @curTime=1) set @rQty -= @yuLiao;
    170             
    171              -- 修正本次要配料数量
    172             if @rQty < 0
    173             begin
    174               set @itemSendQty = @rQty + @itemSendQty;
    175             end
    176             
    177             -- 判断是合并行,还是新建行
    178             declare @existId int = 0;
    179             select @existId = Id from @result where [WorkOrderNo]=@rWorkOrderNo and [ParentItem]=@rParentItem and [Jon]=@rJon and [ItemNo]=@rItemNo and [CycleTime]=@shiftStart
    180 
    181             if @reqType = '95' or @reqType = '99'
    182             begin
    183                 -- 插入欠品数据
    184                 --if @existId > 0 
    185                 --begin
    186                 --  update @result set QtyQp = QtyQp + @itemSendQty where Id=@existId;
    187                 --end
    188                 --else
    189                 if (@existId < 1)
    190                 begin
    191                   insert into @result(Id,[WorkOrderNo],[ParentItem],[Jon],[Workshop],[StartDate],[CycleTime],[ItemNo], Qty, [QtyQp], [ExtrNo], [Whs], [Keeper]) 
    192                   values(@Id, @rWorkOrderNo , @rParentItem , @rJon , @rWorkshop , convert(varchar(10),@rWorkStartDate,120), @shiftStart , @rItemNo , 0, case when (@yuLiao>0 and @curTime=1) then @itemSendQty + @yuLiao else @itemSendQty end, @extrNo, @rWhs, @rKeeper);
    193                 end
    194             end
    195             else if (@reqType = '31')
    196             begin
    197                 -- 插入配料信息
    198                 if @existId > 0 
    199                 begin
    200                   update @result set Qty = Qty + @itemSendQty where Id=@existId;
    201                 end
    202                 else
    203                 begin
    204                   insert into @result(Id,[WorkOrderNo],[ParentItem],[Jon],[Workshop],[StartDate],[CycleTime],[ItemNo], Qty, [QtyQp], [ExtrNo], [Whs], [Keeper]) 
    205                   values(@Id, @rWorkOrderNo , @rParentItem , @rJon , @rWorkshop , convert(varchar(10),@rWorkStartDate,120), @shiftStart , @rItemNo , case when (@yuLiao>0 and @curTime=1) then @itemSendQty + @yuLiao else @itemSendQty end, 0, @extrNo, @rWhs, @rKeeper);
    206                 end
    207 
    208                 -- 如果行剩余数<=0,再次从出库池获取欠品数据                
    209                 if(@rQty <= 0)
    210                 begin
    211                     declare @temQp decimal = 0;-- 总欠品数
    212                     select @temQp = sum(QTY) from EXTR where ITEM_NO=@rItemNo and JON=@rJon and PARENT_ITEM_NO=@rParentItem and WS_CD=@rWorkshop and (REQ_TYPE=99 or REQ_TYPE=95)
    213                     if(@temQp > 0 and @yijing = 0)
    214                     begin
    215                       set @yijing = 1; -- 已经读取过一次的欠品不再读取
    216                       declare @temRqp int = 0; -- 本次操作的欠品数
    217                       set @temRqp = @mpqQty - @itemSendQty; -- 考虑MPQ后的配送数 - 当前行已配送数 = 当前行仍需欠品数
    218                       set @temQp -= @temRqp;
    219                       if(@temQp <= 0) set @temRqp += @temQp; 
    220                       
    221                       -- 若已经到本班次最后一次配送,则全部配送完
    222                       if(@curTime >= @sendTimes)
    223                       begin
    224                         set @temRqp = @temQp;
    225                         set @temQp = 0;
    226                       end
    227                       update @result set QtyQp = @temRqp where Id = @id; -- 更新当前行的欠品数
    228                       set @shiftStart += (@temRqp + @itemSendQty) / @standQty * @freq; -- 修改下次配送时点
    229                       
    230                       while(@temQp > 0) -- 持续把欠品数分配完
    231                       begin
    232                         set @temRqp = @mpqQty;
    233                         if(@shiftStart >= @lastTime) -- 若到最后一次配送时点,则把剩余欠品全部计算
    234                         begin 
    235                           set @shiftStart = @lastTime;
    236                           set @temRqp = @temQp;
    237                           set @temQp = 0;
    238                         end
    239                         else set @temQp -= @temRqp;
    240                         if(@temQp <= 0) set @temRqp += @temQp;
    241                         set @id += 1;
    242 
    243                         -- 插入下一个配送时点的欠品数据
    244                         insert into @result(Id,[WorkOrderNo],[ParentItem],[Jon],[Workshop],[StartDate],[CycleTime],[ItemNo], Qty, [QtyQp], [ExtrNo], [Whs], [Keeper]) 
    245                         values(@Id, @rWorkOrderNo , @rParentItem , @rJon , @rWorkshop , convert(varchar(10),@rWorkStartDate,120), @shiftStart , @rItemNo , 0, @temRqp, @extrNo, @rWhs, @rKeeper);
    246                         set @shiftStart += @temRqp / @standQty * @freq; -- 更新配送时点
    247                       end                  
    248                     end
    249                 end
    250             end
    251 
    252             -- 发货时间点增加
    253             set @shiftStart += @itemSendQty / @standQty * @freq;
    254             if @shiftStart >= 24 
    255             begin
    256               set @shiftStart %= 24;
    257               set @rWorkStartDate = DATEADD(DAY, 1, @rWorkStartDate)
    258             end
    259           end
    260 
    261         -- 获取下一行
    262         fetch next from kitItemRow into @rId, @rWorkOrderNo, @rParentItem, @rJon, @rWorkshop, @rWorkStartDate, @rItemNo, @rQty, @shiftStart, @reqType, @qty , @extrNo, @rWhs, @rKeeper;
    263     end
    264 
    265     -- 关闭游标
    266     close kitItemRow;
    267     -- 释放游标
    268     DEALLOCATE kitItemRow;
    269 
    270     -- 返回结果
    271     --SELECT [WorkOrderNo], [ParentItem], [Jon], [Workshop], [StartDate], [CycleTime], [ItemNo], [Qty], [QtyQp], [Keeper], [Whs] from @result 
    272     --where qty>0 and qtyqp > 0 
    273     --group by [ParentItem],[Jon],[Workshop],[StartDate],[CycleTime],[ItemNo]
    274     --order by [StartDate],[CycleTime], WorkOrderNo, [ItemNo];
    275     RETURN 
    276 END
  • 相关阅读:
    string.Join()用法
    从List分组后重新组织数据
    Java学习笔记05--字符串
    Java学习笔记03--判断与循环语句
    Java学习笔记04--数组
    Java学习笔记02--运算符、表达式
    Java学习笔记01--数据类型
    Spring面试问答
    115个Java面试题和答案——终极列表(下)
    115个Java面试题和答案——终极列表(上)
  • 原文地址:https://www.cnblogs.com/jonney-wang/p/9345912.html
Copyright © 2020-2023  润新知