0

我有下表,其中除 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 和 6var1value以及 5,8 的更改var2value):

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 字符串?

消息 203,级别 16,状态 2,第 53 行
名称 '@declare Eleanor as Int = 42;
while (@Eleanor > 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' 不是有效的标识符。

4

2 回答 2

0

完全重复: SQL QUERY 用前一个已知值中的值替换一行中的 NULL 值 ps:我没有发表评论的特权。所以我写了答案。

于 2012-07-05T18:27:29.027 回答
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
于 2012-07-05T17:52:34.700 回答