首先我很抱歉,如果这是一个重复的问题,但我不知道如何搜索它。这是我的问题。
我有一个从存储过程填充的表。此sp执行大量计算,然后更新表。最后一次计算是长度字段的批量数量和。我运行一个游标(我知道不好主意,但我的老板想要这样)并且在游标中我有第二个游标运行。外部光标从table-1中拉出行(标记#,qty,length),然后将长度与之前的拉长度进行比较,如果它们匹配则将数量加起来。
虽然存储过程运行并且几乎完成了应该执行的操作。问题是如果标记号不是连续的(例1,2,3),它将把总数放在所有具有相同长度的行中。
以下是报告当前的输出方式:
Mark# |Qty |Length |Batch Qty
---------------------------------
1214-G30|112 |41.4882 |770
---------------------------------
1214-G33|84 |41.4882 |770
---------------------------------
1214-G38|574 |41.4882 |770
---------------------------------
我需要的是以下输出:
Mark# |Qty |Length |Batch Qty
---------------------------------
1214-G30|112 |41.4882 | -
---------------------------------
1214-G33|84 |41.4882 | -
---------------------------------
1214-G38|574 |41.4882 |770
---------------------------------
以下是完成所有工作的存储过程:
--Clear CrossBar Report Table
Truncate Table tbl_CrossBarRpt
--Check for open Cursor
If (CURSOR_STATUS('global', 'FACursor'))>=-1
Begin
If (Select CURSOR_STATUS('global', 'FACursor'))>-1
Begin
Close FACursor
End
Deallocate FACursor
End
--Dump base data into Cross Bar Report Table
Insert Into tbl_CrossBarRpt(ordernum, materialdesc, marknum)
Select oh.ordernum,gt.material_descFS, od.marknum
From tbl_order_head oh
Join tbl_order_detail od
ON oh.ordernum = od.ordernum
Join tbl_grating_type gt
On oh.gratingnum = gt.grating_type
Where oh.ordernum = @ordernum
--Set variables based on order Number
Declare @bbin as Decimal(18,4); --Bearing Bar Inches
Declare @cbd as Decimal(18,4); --Cross bar Divider
Declare @mtth as Decimal(18,4); --Mount Thickness
Declare @tsp as Decimal(18,4); --Tolerance Support Rod
Declare @tfr as Decimal(18,4); --Tolerance Filling Rod
Declare @totqty as Int; --Total Quantity
Declare @length as Decimal(18,4); --Length
Declare @FA as Decimal(18,4); --Variable FA
Declare @TEM as Decimal(18,4); --Variable TEM
Declare @MEMT as Decimal(18,4); --variable MEMT
--Declare @ReturnValue Decimal(18,4); --Return FA value
--Set Cross Bar Divider
--Exec @cbd = sp_GetCrossbarDivider @ordernum;
Set @cbd = (Select gt.cross_bar_divider
From tbl_grating_type gt
Join tbl_order_head oh
On oh.gratingnum = gt.grating_type
Where oh.ordernum = @ordernum)
--Set Mounting Thickness
--Exec @mtth = sp_GetMountingThickness @ordernum;
Set @mtth = (Select mt.mnt_thickness
From tbl_mount mt
Join tbl_order_head oh
On oh.banding = mt.mnt_designation
Where oh.ordernum = @ordernum)
--Set Tolerance Support Rod
--Exec @tsp = sp_GetTolerance @ordernum;
Set @tsp = (Select tl.tol_support_rod
From tbl_tolerance tl
Join tbl_order_head oh
On oh.tolerance = tl.tol_description
Where oh.ordernum = @ordernum)
--Set Tolerance Filling Rod
Set @tfr = (Select tl.tol_filling_rod
From tbl_tolerance tl
Join tbl_order_head oh
On oh.tolerance = tl.tol_description
Where oh.ordernum = @ordernum)
--Set Tolerance Support Rod min Mesh
--Exec @MEMT = sp_GetToleranceMesh @ordernum;
Set @MEMT = (Select tl.tol_support_rod_min_mesh
From tbl_tolerance tl
Join tbl_order_head oh
On oh.tolerance = tl.tol_description
Where oh.ordernum = @ordernum)
--Set up cursor for CrossBar input value
Declare @BearingBar Decimal(18,4);
Declare @CrossBar Decimal(18,4);
Declare @MarkNum as varchar(25);
Declare @Qty as Int;
Declare FACursor Cursor
For
Select od.bbin, od.cbin, od.marknum, od.qty
From tbl_order_detail od
Where od.ordernum = @ordernum
Open FACursor
Fetch Next From FACursor Into
@BearingBar, @Crossbar, @MarkNum, @Qty
While @@FETCH_STATUS = 0
Begin
--Calculate FA
Set @FA = Round((@BearingBar*25.4)/@cbd,0,1)
Set @TEM = (((@BearingBar * 25.4) - @mtth - @mtth - @tsp) - ((@FA -1) * @cbd))/2
If (@TEM < @MEMT)
Begin
Set @FA = @FA -1
Set @TEM = (((@BearingBar * 25.4) - @mtth - @mtth - @tsp) - ((@FA -1) * @cbd))/2
If (@TEM < @MEMT)
Begin
Set @FA = @FA -1
Set @TEM = (((@BearingBar * 25.4) - @mtth - @mtth - @tsp) - ((@FA -1) * @cbd))/2
End
End
If (@TEM < ((@cbd/2) + (@cbd*.05)))
Begin
Set @FA = @FA -1
Set @TEM = (((@BearingBar * 25.4) - @mtth - @mtth - @tsp) - ((@FA -1) * @cbd))/2
End
--Calculate Total Qty
Set @totqty = @Qty * @FA
--Insert Total Qty value into table Cross Bar Report
Update tbl_CrossBarRpt Set totqty = @totqty Where marknum = @MarkNum
--Calculate Length Value
Set @length = ((@CrossBar *25.4)-@tfr)/25.4
--Insert Length value into table Cross Bar Report
Update tbl_CrossBarRpt Set length = @length Where marknum = @MarkNum
--Get next row of data
Fetch Next From FACursor Into
@BearingBar, @Crossbar, @MarkNum, @Qty
End
--Close Cursor
If (CURSOR_STATUS('global', 'FACursor'))>=-1
Begin
If (Select CURSOR_STATUS('global', 'FACursor'))>-1
Begin
Close FACursor
End
Deallocate FACursor
End
--Create Temp table for Batch Qty Processing
Select cbr.marknum, cbr.totqty, cbr.length
into #tbl_BQProcess
From tbl_CrossBarRpt cbr
Order By cbr.length Desc, cbr.marknum
--Set up variables for Batch Qty Processing Cursor
Declare @bMarknum as varchar(25);
Declare @bTotQty as int = 0;
Declare @bLeng as decimal(18,4) = 0.0000;
Declare @bLength1 as decimal (18,4) = 0.0000;
Declare @bLength2 as Decimal(18,4) = 0.0000;
Declare @bQty as int = 0;
Declare @bPrevLeng as decimal(18,4) = 0.0000;
Declare BQOutterCursor Cursor
For
Select cr.marknum, cr.totqty, cr.length
From tbl_CrossBarRpt cr
Where cr.ordernum = @ordernum
Open BQOutterCursor
Fetch Next From BQOutterCursor Into
@bMarkNum, @bTotQty, @bLeng
While @@FETCH_STATUS = 0
Begin
If @bPrevLeng = @bLeng
Begin
Goto Cont
End
Else
Begin
Declare @ibMarknum as varchar(25);
Declare @ibTotQty as int = 0;
Declare @ibLeng as decimal(18,4) = 0.0000;
Declare @ibLength1 as decimal (18,4) = 0.0000;
Declare @ibLength2 as Decimal(18,4) = 0.0000;
Declare @ibQty as int = 0;
Declare BQInnerCursor Cursor
For
Select bqp.marknum, bqp.totqty, bqp.length
From #tbl_BQProcess bqp
Order by bqp.length Desc, bqp.marknum
Open BQInnerCursor
Fetch Next From BQInnerCursor Into
@ibMarkNum, @ibTotQty, @ibLeng
While @@FETCH_STATUS = 0
Begin
If @ibLeng = @bLeng
Begin
Set @ibQty = @ibQty + @ibTotQty
End
Fetch Next From BQInnerCursor Into
@ibMarkNum, @ibTotQty, @ibLeng
End
End
--Update batch Qty totals
Update tbl_CrossBarRpt
Set batchqty = @ibQty
Where marknum = @bMarknum
--Close Inner Cursor
If (CURSOR_STATUS('global', 'BQInnerCursor'))>=-1
Begin
If (Select CURSOR_STATUS('global', 'BQInnerCursor'))>-1
Begin
Close BQInnerCursor
End
Deallocate BQInnerCursor
End
Cont:
--Update Prev Length to current length
Set @bPrevLeng = @bLeng
Fetch Next From BQOutterCursor Into
@bMarkNum, @bTotQty, @bLeng
End
--Close Outter Cursor
If (CURSOR_STATUS('global', 'BQOutterCursor'))>=-1
Begin
If (Select CURSOR_STATUS('global', 'BQOutterCursor'))>-1
Begin
Close BQOutterCursor
End
Deallocate BQOutterCursor
End
--Drop temp table
Drop Table #tbl_BQProcess
有没有人对如何保留重复内容有任何想法。
提前致谢。
答案 0 :(得分:2)
我不确定为什么坚持使用游标,但我认为你的整个外部和内部游标都可以被替换为:
select cbr.marknum,
cbr.length,
case when row_number() over(partition by cbr.length order by cbr.length desc, cbr.marknum desc) = 1
then sum(cbr.totqty) over (partition by cbr.length order by cbr.length, cbr.marknum) else null end batchqty
from tbl_CrossBarRpt cbr
order by length, marknum
如果您需要使用batchqty实际更新tbl_CrossBarRpt
而不是仅选择值,则可以这样做:
update tbl_CrossBarRpt
set batchqty = x.batchqty
from tbl_CrossBarRpt t
join (select cbr.marknum,
case when row_number() over(partition by cbr.length order by cbr.length desc, cbr.marknum desc) = 1
then sum(cbr.totqty) over (partition by cbr.length order by cbr.length, cbr.marknum) else null end batchqty
from tbl_CrossBarRpt cbr) x on x.marknum = t.marknum