从 SQL 个计算列中删除重复项
Remove duplicates from SQL calculated column
首先,如果这是一个重复的问题,我很抱歉,但我不确定如何搜索它。这是我的问题。
我有一个从存储过程填充的 table。该 sp 执行大量计算,然后更新 table。最后的计算是按长度字段计算的批次数量总和。我 运行 一个游标(我知道这是个坏主意,但我的老板希望这样)并且在那个游标中我有第二个游标 运行s。外部游标从 table-1 (mark#, qty, length) 中拉取行,然后将长度与先前拉取的长度进行比较,如果它们匹配,则将数量相加。
虽然存储过程 运行s 并且几乎完成了应该做的事情。问题是,如果标记编号不是连续的(示例 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
有没有人对我如何避免重复有任何想法。
提前致谢。
我不确定为什么坚持使用游标,但我认为你的整个外部和内部游标都可以用这个代替:
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
首先,如果这是一个重复的问题,我很抱歉,但我不确定如何搜索它。这是我的问题。
我有一个从存储过程填充的 table。该 sp 执行大量计算,然后更新 table。最后的计算是按长度字段计算的批次数量总和。我 运行 一个游标(我知道这是个坏主意,但我的老板希望这样)并且在那个游标中我有第二个游标 运行s。外部游标从 table-1 (mark#, qty, length) 中拉取行,然后将长度与先前拉取的长度进行比较,如果它们匹配,则将数量相加。
虽然存储过程 运行s 并且几乎完成了应该做的事情。问题是,如果标记编号不是连续的(示例 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
有没有人对我如何避免重复有任何想法。
提前致谢。
我不确定为什么坚持使用游标,但我认为你的整个外部和内部游标都可以用这个代替:
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