用SQL查詢分析實現類似金蝶K3的收發存明細表


使用SQL查詢分析實現類收發存的報表,原始需求在 另外一篇文章 的第四部分。下圖是實現需求。

Snipaste_2020-04-26_13-58-25.png

一、准備

刪除臨時表


[buy]判斷是否存在臨時表,存在則刪除[/buy]

if OBJECT_ID('tempdb..#inv') is not null        
drop table #inv
if OBJECT_ID('tempdb..#t_mto') is not null        
drop table #t_MTO
if OBJECT_ID('tempdb..#t_mtoentry') is not null        
drop table #t_MTOEntry

判斷是否存在需調整記錄

[buy]判斷采購申請單上是否存在需要調整的記錄,存在則繼續。
需要滿足條件是:
1.采購申請單上存在MTO計划模式的物料,計划跟蹤號不為999999;
2.庫存中有可調整的物料。
那么庫存中哪些是可以調整的物料呢?還得滿足以下條件:
2.1批號為999999;
2.2計划跟蹤號為空或者999999;
3.3無浮動計量單位的,基本庫存數量要大於0,有浮動計量單位的,輔助數量和基本數量的庫存均需大於0;
[/buy]

declare @finterid int = 1059
if exists (select f1 from (
     select case when (ti.FSecUnitID = 0 and t2.FQty > 0) OR (ti.FSecUnitID > 0 and t2.FQty > 0 and t2.FSecQty > 0 ) then 1 else 0 end as "F1"  
		 from  PORequestEntry t1
		 left join ICInventory t2 on t1.FItemID = t2.FItemID
		 left join t_ICItem ti on t1.FItemID = ti.FItemID
		 where t1.FInterID = @finterid
			and t1.FPlanMode = '14035'
			and t1.FMTONo <> '999999'
			and t2.FBatchNo = '999999'
			and t2.FMTONo in ('','999999')
	 ) as t where f1 = 1
)

二、開始

begin

尋找內碼

查詢mto調整單的內碼

	declare @maxNum int
	select @maxNum = FMaxNum from ICMaxNum where FTableName = 't_MTOChange'
	set @maxNum = @maxNum + 1
	update ICMaxNum set FMaxNum = @maxNum

構建表結構

將采購申請、存貨表、需計算的字段進行聯結,並構成臨時表#inv

	select 	
		t3.FBillNo,
		t1.FEntryID,
		t1.FDetailID,
		t1.FItemID,
		t1.FMTONo as "t1FMTONo",
		ti.FSecUnitID,
		t1.FQty as "t1FQty",
		t1.FCommitQty,
		t1.FUnitID,
		tm.FCoefficient,
		t1.FAuxCommitQty,
		t1.FAuxQty,
		t1.FSecQty as "t1FSecQty",
		t1.FSecCommitQty,
		t1.FOrderQty,
		t1.FMRPClosed,
		t1.FPlanMode,
		t1.FEntrySelfP0139, --輔助數量(計算)
		t1.FEntrySelfP0140, --關聯數量
		t1.FEntrySelfP0141,  --關聯標志
		t2.FStockID,
		t2.FStockPlaceID,
		t2.FKFPeriod,
		t2.FKFDate,
		t2.FQty as "t2FQty",
		t2.FSecQty as "t2FSecQty",
		case when t2.FSecQty > 0 then t2.FQty / t2.FSecQty else 0 end as "FSecCoefficient",
		t2.FBatchNo,
		t2.FMTONo as "t2FMTONo",
		CAST(null as int) as "FMTOInterID",
		CAST(null as decimal(28,10)) as "FChaQty",
		cast(null as decimal(28,10)) as "FMTOChange",
		cast(null as decimal(28,10)) as "FSumMTOChange",
		CAST(null as decimal(28,10)) as "FBegQty",
		CAST(null as decimal(28,10)) as "FEndQty",
		
		cast(null as decimal(28,10)) as "FSecChaQty",
		cast(null as decimal(28,10)) as "FSecMTOChange",
		cast(null as decimal(28,10)) as "FSecSumMTOChange",
		CAST(null as decimal(28,10)) as "FSecBegQty",
		CAST(null as decimal(28,10)) as "FSecEndQty",
	
		DENSE_RANK() OVER (ORDER BY t1.FItemID) AS RANK1,
		ROW_NUMBER() over (PARTITION by t1.FDetailID order By t1.FEntryID,t2.FMTONo,t2.FQty desc) RANK2

	 into #inv
	 from PORequestEntry t1
	 left join ICInventory t2 on t1.FItemID = t2.FItemID
	 left join t_ICItem ti on t1.FItemID = ti.FItemID
	 left join t_MeasureUnit tm on t1.FUnitID = tm.FMeasureUnitID
	 left join PORequest t3 on t1.FInterID =t3.FInterID
	 where t1.FInterID = @finterid
		and t1.FPlanMode = '14035'
		and t1.FMTONo <> '999999'
		and t2.FBatchNo = '999999'
		and t2.FMTONo in ('','999999')
		and t2.FQty > 0
		and ((ti.FSecUnitID = 0 and t2.FQty > 0) OR (ti.FSecUnitID > 0 and t2.FQty > 0 and t2.FSecQty > 0 ))

更新

更新#inv表的MTO調整單內碼

	update #inv set FMtoInterID = @maxNum

構建臨時表

用來存放mto調整單的表頭數據

	create table #t_MTO(
		FID int,
		FClassTypeID int,
		FTranType int,
		FBillNo nvarchar(255),
		FDate datetime,
		FNote nvarchar(255),
		FBillerID int,
		FCheckDate datetime,
		FEmpID int,
		FCheckerID int,
		FDeptID int,
		FStatus smallint,
		FUpStockWhenSave bit,
		FPrintCount int,
		FSourceBillNo nvarchar(50),
		FSourceTranType int
	)

用來存放mto調整單的表體數據

	create table #t_MTOEntry(
		FID int,
		FIndex int,
		FItemID int,
		FAuxPropID int,
		FBatchNo varchar(255),
		FStockID int,
		FSPID int,
		FBaseQty decimal(23,10),
		FSecUnitID int,
		FUnitID int,
		FQty decimal(23,10),
		FSecCoefficient decimal(23,10),
		FSecQty decimal(23,10),
		FChangeQty_Base decimal(23,10),
		FChangeQty decimal(23,10),
		FChangeSecQty decimal(23,10),
		FKFDate datetime,
		FKFPeriod int,
		FPeriodDate datetime,
		FFromMTONo nvarchar(50),
		FToMTONo nvarchar(50),
		FChangeBaseQty decimal(23,10),
		FSelectedProcID int,
		FEntrySupply int,
		FStockTypeID int,
		FMrpNo nvarchar(50)
	)

三、計算

	declare @R1 int = 1
	declare @maxR int = (select MAX(RANK1) from #inv)
	while @R1 <= @maxR begin
		if OBJECT_ID('tempdb..#inv2') is not null        
		drop table #inv2
		select *,DENSE_RANK() OVER (ORDER BY FDetailID) AS RANK3 into #inv2 from #inv where RANK1 = @R1
		
		declare @FSecUnitID int = (select top(1) FSecUnitID from #inv2 where RANK1 = @R1)
		
		if @FSecUnitID = 0 begin --沒有輔助單位的
			declare @R2 int = 1
			declare @maxR2 int = (select MAX(RANK2) from #inv2 where  RANK3 = 1)
			declare @FChaQty decimal(28,10) = (select t1FQty from #inv2 where  RANK2 = 1 and RANK3 = 1)
			while @R2 <= @maxR2 begin
				set @FChaQty = @FChaQty - (select t2FQty from #inv2 where RANK2 = @R2 and RANK3 = 1) 
				update #inv2 set FChaQty = @FChaQty where RANK2 = @R2 and RANK3 = 1
				if @FChaQty > 0 update #inv2 set FMTOChange = t2FQty where RANK2 = @R2 and RANK3 = 1
				if @FChaQty <=0 update #inv2 set FMTOChange = t2FQty + FChaQty where RANK2 = @R2 and RANK3 = 1
				update #inv2 set FSumMTOChange = (select SUM(FMTOChange) from #inv2 where RANK3 = 1 and FMTOChange > 0) where  RANK3 = 1
				update #inv2 set FMRPClosed = case when (FSumMTOChange - t1FQty >= 0 ) then 1 else 0 end where RANK3 = 1
				update #inv2 set FEndQty = t2FQty - FMTOChange where RANK3 = 1 and FMTOChange > 0
				update #inv2 set FEndQty = t2FQty where RANK3 = 1 and FMTOChange <= 0
				set @R2 = @R2 +1
			end

			declare @R3 int = 1
			declare @maxR3 int = (select MAX(RANK3) from #inv2)
			while @R3 <= @maxR3 begin
				
				declare @i int = 1
				declare @maxI int = (select MAX(rank2) from #inv2 where RANK3 = @R3)
				while @i <= @maxI begin
					update #inv2 set FBegQty = t2FQty where RANK2 = @i and RANK3 = 1
					update #inv2 set FBegQty = (select FEndQty from #inv2 where RANK2 = @i and RANK3 = @R3 and FEndQty >0) where RANK2 = @i and RANK3 = @R3+1
					set @i = @i + 1		
				end
				
				declare @R31 int = 2
				while @R31 <= @maxR3 begin
					
					declare @j int = (select min(RANK2) from #inv2 where FBegQty >0 and RANK3 = @R31)
					declare @maxJ int =  (select max(RANK2) from #inv2 where FBegQty >0 and RANK3 = @R31)
					declare @FChaQty2 decimal(28,10)= (select t1FQty from #inv2 where RANK2 = 1 and RANK3 = @R31)
					while @j <= @maxJ begin
						set @FChaQty2 = @FChaQty2 - (select FBegQty from #inv2 where RANK2 = @j and RANK3 = @R31)
						update #inv2 set FChaQty = @FChaQty2 where RANK2 = @j and RANK3 = @R31
						if @FChaQty2 > 0 update #inv2 set FMTOChange = FBegQty where RANK2 = @j and RANK3 = @R31
						if @FChaQty2 <=0 update #inv2 set FMTOChange = FBegQty + FChaQty where RANK2 = @j and RANK3 = @R31
						update #inv2 set FSumMTOChange = (select SUM(FMTOChange) from #inv2 where RANK3 = @R31 and FMTOChange >0) where  RANK3 = @R31 
						update #inv2 set FMRPClosed = case when (FSumMTOChange - t1FQty >= 0 ) then 1 else 0 end where RANK3 = @R31
						update #inv2 set FEndQty = FBegQty - FMTOChange where RANK3 = @R31 and FMTOChange > 0
						update #inv2 set FEndQty = FBegQty where RANK3 = @R31 and FMTOChange <= 0
						set @j = @j+1
					end 
					set @R31 = @R31 +1
				end
				set @R3 = @R3 + 1		
			end	
		end
		
		if @FSecUnitID >0 begin --有輔助單位的
			declare @R2s int = 1
			declare @maxR2s int = (select MAX(RANK2) from #inv2 where  RANK3 = 1)
			declare @FSecChaQty decimal(28,10) = (select FEntrySelfP0139 from #inv2 where  RANK2 = 1 and RANK3 = 1)
			while @R2s <= @maxR2s begin
				set @FSecChaQty = @FSecChaQty - (select t2FSecQty from #inv2 where RANK2 = @R2s and RANK3 = 1) 
				update #inv2 set FSecChaQty = @FSecChaQty where RANK2 = @R2s and RANK3 = 1
				if @FSecChaQty > 0 update #inv2 set FSecMTOChange = t2FSecQty where RANK2 = @R2s and RANK3 = 1
				if @FSecChaQty <=0 update #inv2 set FSecMTOChange = t2FSecQty + FSecChaQty where RANK2 = @R2s and RANK3 = 1
				update #inv2 set FSecSumMTOChange = (select SUM(FSecMTOChange) from #inv2 where RANK3 = 1 and FSecMTOChange > 0) where RANK3 = 1
				update #inv2 set FMRPClosed = case when (FSecSumMTOChange - FEntrySelfP0139 >= 0 ) then 1 else 0 end where RANK3 = 1
				update #inv2 set FSecEndQty = t2FSecQty - FSecMTOChange where RANK3 = 1 and FSecMTOChange > 0
				update #inv2 set FSecEndQty = t2FSecQty where RANK3 = 1 and FSecMTOChange <= 0
				
				update #inv2 set FMTOChange = FSecMTOChange * FSecCoefficient where RANK2 = @R2s and RANK3 = 1
				update #inv2 set FSumMTOChange = (select SUM(FMTOChange) from #inv2 where RANK3 = 1 and FMTOChange > 0) where RANK3 = 1
				update #inv2 set FEndQty = t2FQty - FMTOChange where RANK3 = 1 and FMTOChange > 0
				update #inv2 set FEndQty = t2FQty where RANK3 = 1 and FMTOChange <= 0
				set @R2s = @R2s +1
			end

			declare @R3s int = 1
			declare @maxR3s int = (select MAX(RANK3) from #inv2)
			while @R3s <= @maxR3s begin
				
				declare @is int = 1
				declare @maxIs int = (select MAX(rank2) from #inv2 where RANK3 = @R3s)
				while @is <= @maxIs begin
					update #inv2 set FSecBegQty = t2FSecQty where RANK2 = @is and RANK3 = 1
					update #inv2 set FSecBegQty = (select FSecEndQty from #inv2 where RANK2 = @is and RANK3 = @R3s and FSecEndQty >0) where RANK2 = @is and RANK3 = @R3s+1
					
					update #inv2 set FBegQty = t2FQty where RANK2 = @is and RANK3 = 1
					update #inv2 set FBegQty = (select FEndQty from #inv2 where RANK2 = @is and RANK3 = @R3s and FEndQty >0) where RANK2 = @is and RANK3 = @R3s+1
					set @is = @is + 1		
				end
				
				declare @R31s int = 2
				while @R31s <= @maxR3s begin
					
					declare @js int = (select min(RANK2) from #inv2 where FSecBegQty >0 and RANK3 = @R31s)
					declare @maxJs int =  (select max(RANK2) from #inv2 where FSecBegQty >0 and RANK3 = @R31s)
					declare @FSecChaQty2 decimal(28,10)= (select FEntrySelfP0139 from #inv2 where RANK2 = 1 and RANK3 = @R31s)
					while @js <= @maxJs begin
						set @FSecChaQty2 = @FSecChaQty2 - (select FSecBegQty from #inv2 where RANK2 = @js and RANK3 = @R31s)
						update #inv2 set FSecChaQty = @FSecChaQty2 where RANK2 = @js and RANK3 = @R31s
						if @FSecChaQty2 > 0 update #inv2 set FSecMTOChange = FSecBegQty where RANK2 = @js and RANK3 = @R31s
						if @FSecChaQty2 <=0 update #inv2 set FSecMTOChange = FSecBegQty + FSecChaQty where RANK2 = @js and RANK3 = @R31s
						update #inv2 set FSecSumMTOChange = (select SUM(FSecMTOChange) from #inv2 where RANK3 = @R31s and FSecMTOChange >0) where RANK3 = @R31s
						update #inv2 set FMRPClosed = case when (FSecSumMTOChange - FEntrySelfP0139 >= 0 ) then 1 else 0 end where RANK3 = @R31s
						update #inv2 set FSecEndQty = FSecBegQty - FSecMTOChange where RANK3 = @R31s and FSecMTOChange > 0
						update #inv2 set FSecEndQty = FSecBegQty where RANK3 = @R31s and FSecMTOChange <= 0
						
						update #inv2 set FMTOChange = FSecMTOChange * FSecCoefficient where RANK2 = @js and RANK3 = @R31s
						update #inv2 set FSumMTOChange = (select SUM(FMTOChange) from #inv2 where RANK3 = @R31s and FMTOChange > 0 ) where RANK3 = @R31s
						update #inv2 set FEndQty = FBegQty - FMTOChange where RANK3 = @R31s and FMTOChange > 0
						update #inv2 set FEndQty = FBegQty where RANK3 = @R31s and FMTOChange <= 0
						set @js = @js+1
					end 
					set @R31s = @R31s +1
				end
				set @R3s = @R3s + 1		
			end	
		end
		
		select * from #inv2

四、結束

反寫采購申請明細表

		update te set 
			te.FMRPClosed = ti.FMRPClosed,
			te.FCommitQty = ti.FSumMTOChange,
			te.FAuxCommitQty = ti.FSumMTOChange / ti.FCoefficient,
			te.FSecCommitQty = case when ti.FSecSumMTOChange IS null then 0 else ti.FSecSumMTOChange end,
			te.FOrderQty = ti.FSumMTOChange,
			te.FEntrySelfP0140 = case when ti.FSecUnitID = 0 then ti.FSumMTOChange else ti.FSecSumMTOChange end,
			te.FEntrySelfP0141 = 1
			from PORequestEntry te,#inv2 ti where te.FDetailID = ti.FDetailID

插入MTO單據體臨時表

		insert into #t_MTOEntry 
			select 
			FMTOInterID,
			'' as "FIndex",
			FItemID,
			'0' as "FAuxPropID",
			FBatchNo,
			FStockID,
			FStockPlaceID,
			FBegQty,
			null as "FSecUnitID",
			FUnitID,
			FBegQty / FCoefficient as "FQty",
			FSecCoefficient,
			case when FSecBegQty is null then 0 else FSecBegQty end as "FSecQty",
			'0' as FChangeQty_Base,
			FMTOChange / FCoefficient as "FChangeQty",
			case when FSecMTOChange is null then 0 else FSecMTOChange end as "FChangeSecQty",
			case when (FKFDate = '') then null else FKFDate end AS "FKFDate",
			FKFPeriod,
			case when (FKFDate = '') then null else FKFDate + FKFPeriod end AS "FPeriodDate",
			t2FMTONo,
			t1FMTONo,
			FMTOChange,
			'',
			'',
			'',
			''
		    from #inv2 where FMTOChange > 0 
		set @R1 = @R1+1
	end

插入MTO單據頭臨時表

	insert into #t_MTO 
			select 
			FMTOInterID,
			1107011,
			1107011,
			'MTOAUTO'+LTRIM(str(FMTOInterID)),
			CONVERT(varchar(10),getdate(),23)+' 00:00:00.000',
			'',
			16394,
			GETDATE(),
			2649,
			16394,
			277,
			1,
			0,
			0,
			FBillNo,
			70
			from #inv2

插入數據表

	insert into t_MTOChange select * from #t_MTO
	insert into t_MTOChangeEntry select * from #t_MTOEntry

插入審批流

	Insert Into ICClassCheckRecords1107011(FPage,FBillID,FBillEntryID,FBillNo, FBillEntryIndex,FCheckLevel,FCheckLevelTo,FMode,FCheckMan, FCheckIdea,FCheckDate,FDescriptions)  
		Values (1,@maxnum,0,'MTOAUTO'+ltrim(str(@maxnum)),0,-99,-1,0,16394,'',GetDate(),'審核')
	Insert Into ICClassCheckRecords1107011(FPage,FBillID,FBillEntryID,FBillNo, FBillEntryIndex,FCheckLevel,FCheckLevelTo,FMode,FCheckMan, FCheckIdea,FCheckDate,FDescriptions)  
		Values (1,@maxnum,0,'MTOAUTO'+ltrim(str(@maxnum)),0,-1,1,0,16394,'',GetDate(),'審核')

校對即時庫存

	EXEC CheckInventory

更新采購申請單單據頭MTO內碼

	update PORequest set FChildren = FChildren + 1,FHeadSelfP0134 = @maxNum where FInterID = @finterid

結束

end


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM