继承先前记录中的值

时间:2012-07-05 14:42:01

标签: tsql

我有下表,其中除了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'不是有效的标识符

2 个答案:

答案 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:我没有权利发表评论。所以我写了答案。