我有下表,其中除了Value之外的所有字段都作为表上唯一索引的一部分。我想将Value<>NULL
的记录中的值继承到下一个修订记录,只要该记录具有NULL值(参见下面的示例):
Var[n]Value
个字段吃了varchar,我的表中可能有1个n Var[n]value
个字段。
来源:
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 NULL NULL
1744 6 2 1 NULL SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 NULL
需要的结果(修订记录5和6 var1value
的通知更改以及var2value
的5,8):
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 Tit2 ABD
1744 6 2 1 Tit2 SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 AS
知道如何通过SQL处理它吗?
请告知。
我尝试了以下内容:
declare @TableName as VarChar(32) = 'MYTABLE'
declare @SetClause as VarChar(1024)
declare @LWhereClause as VarChar(1024)
declare @RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = @TableName and Column_Name like 'Var%'
--select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare @ColumnName as VarChar(32)
while ( @@RowCount > 0 )
begin
select top 1 @ColumnName = Column_Name
from #Columns
order by Column_Name
set @SetClause = case when @SetClause is NULL then '' else @SetClause + ', ' end +
@ColumnName + ' = Coalesce( L.' + @ColumnName + ', R.' + @ColumnName + ' )'
set @LWhereClause = case when @LWhereClause is NULL then '' else @LWhereClause + ' or ' end +
'L.' + @ColumnName + ' is NULL'
set @RWhereClause = case when @RWhereClause is NULL then '' else @RWhereClause + ' or ' end +
'R.' + @ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = @ColumnName
end
--select @SetClause, @LWhereClause, @RWhereClause
-- Put together the UPDATE statement.
declare @Update as nVarChar(max)
set @Update=''
set @Update=@Update +
'update L set ' + @SetClause + ' from ' + @TableName +
' as L inner join ' + @TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + @LWhereClause + ' ) and ( ' + @RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare @Loop as nVarChar(max)
set @Loop =''
set @Loop=@Loop+
'@declare Eleanor as Int = 42;
while ( @Eleanor > 0 ) '
+ @Update + '
set @Eleanor = @@RowCount
end'
--select @Loop
-- Execute it.
exec @Loop
drop table #Columns
我在exec循环上得到以下错误。为什么要截断nvarchar字符串?
Msg 203,Level 16,State 2,Line 53
名称'@declare Eleanor as Int = 42;
while(@Eleanor&gt; 0)更新L set variable104 = Coalesce(L.variable104,R.variable104),variable105 = Coalesce(L.variable105,R.variable105),variable106 = Coalesce(L.variable106,R.variable106), variable107 = Coalesce(L.variable107,R.variable107),variable112 = Coalesce(L.variable112,R.variable112),variable116 = Coalesce(L.variable116,R.variable116),variable119 = Coalesce(L.variable119,R.variable119) ),variable120 = Coalesce(L.variable120,R.variable120),variable121 = Coalesce(L.variable121,R.variable121),variable122 = Coalesce(L.variable122,R.variable122),variable124 = Co'不是有效的标识符
答案 0 :(得分:0)
编辑:请原谅,但我没有考虑变量列。
此查询将检索YourTable
中定义的列:
select Column_Name from Information_Schema.Columns where Table_Name = 'YourTable'
此后,您需要构建动态查询并EXEC
。您可以为每个单独的列创建如下所示的代码,或者一次性处理所有列。
动态构建查询是一个有点繁琐的过程。以下内容可以帮助您顺利完成任务。
declare @TableName as VarChar(32) = 'YourTable'
declare @SetClause as VarChar(1024)
declare @LWhereClause as VarChar(1024)
declare @RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = @TableName and Column_Name like 'Var%'
select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare @ColumnName as VarChar(32)
while ( @@RowCount > 0 )
begin
select top 1 @ColumnName = Column_Name
from #Columns
order by Column_Name
set @SetClause = case when @SetClause is NULL then '' else @SetClause + ', ' end +
@ColumnName + ' = Coalesce( L.' + @ColumnName + ', R.' + @ColumnName + ' )'
set @LWhereClause = case when @LWhereClause is NULL then '' else @LWhereClause + ' or ' end +
'L.' + @ColumnName + ' is NULL'
set @RWhereClause = case when @RWhereClause is NULL then '' else @RWhereClause + ' or ' end +
'R.' + @ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = @ColumnName
end
select @SetClause, @LWhereClause, @RWhereClause
-- Put together the UPDATE statement.
declare @Update as VarChar(4096) =
'update L set ' + @SetClause + ' from ' + @TableName +
' as L inner join ' + @TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + @LWhereClause + ' ) and ( ' + @RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare @Loop as VarChar(4096) =
'@declare Eleanor as Int = 42; ...' + @Update + '...'
select @Loop
-- Execute it.
exec @Loop
drop table #Columns
这是一种基于修订号密集的可怕方式:
declare @Docs as Table ( DocId Int, Rev Int, Proj Int, Conf Int, Var1 VarChar(10) Null, Var2 VarChar(10) Null )
insert into @Docs ( DocId, Rev, Proj, Conf, Var1, Var2 ) values
( 1744, 1, 2, 1, NULL, NULL ),
( 1744, 2, 2, 1, NULL, NULL ),
( 1744, 3, 2, 1, 'Tit1', 'ABC' ),
( 1744, 4, 2, 1, 'Tit2', 'ABD' ),
( 1744, 5, 2, 1, NULL, NULL ),
( 1744, 6, 2, 1, NULL, 'SDC' ),
( 1744, 7, 2, 1, '', 'AS' ), -- The example data for this row is unclear.
( 1744, 8, 2, 1, 'Tit3', NULL )
select * from @Docs
declare @Eleanor as Int = 42
while ( @Eleanor > 0 )
begin
update L
set Var1 = Coalesce( L.Var1, R.Var1 ), Var2 = Coalesce( L.Var2, R.Var2 )
from @Docs as L inner join
@Docs as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf
where ( L.Var1 is NULL or L.Var2 is NULL ) and ( R.Var1 is not NULL or R.Var2 is not NULL )
set @Eleanor = @@RowCount
end
select * from @Docs
答案 1 :(得分:0)
完全重复: SQL QUERY replace NULL value in a row with a value from the previous known value p.s:我没有权利发表评论。所以我写了答案。