根据3个表和2个规则更新列

时间:2013-05-13 00:22:18

标签: sql-server-2008

我有三张表如下:

declare @tableA table (id int, name varchar(2));
declare @tableB table (name varchar(2));
declare @tableC table (id int, name varchar(2))
insert into @tableA(id, name)
    select 01, 'A4' union all
    select 01, 'SH' union all
    select 01, '9K' union all
    select 02, 'M1' union all
    select 02, 'L4' union all
    select 03, '2G' union all
    select 03, '99';

insert into @tableB(name)
    select '5G' union all
    select 'U8' union all
    select '02' union all
    select '45' union all
    select '23' union all
    select 'J7' union all
    select '99' union all
    select '9F' union all
    select 'A4' union all
    select 'H2';
insert into @tableC(id)
    select 01 union all
    select 01 union all
    select 01 union all
    select 02 union all
    select 02 union all
    select 03 union all
    select 03;

基本上,@ TableC.ID是从@ TableA.ID(相同的行)填充的

现在,我必须考虑以下规则来填充@ tableC.Name:

  1. 它应该从@ TableB.name获取值,前提是@TableA中相同的ID不应存在相同的@ TableA.name。因此,对于ID = 1,@ TableC.name应该是任何值,但A4,SH,9K。

  2. 每个@ TableC.ID的
  3. @ tableC.Name应为DISTINCT。所以@ TableC.Name对于相同的ID不应该有两个相同的值,但对于不同的ID,它可以具有相同的@ TableC.name。

  4. 我用来解决规则#1的查询是:(请编辑它以应用规则#2)

    update c
        set Name = (select top 1 b.name
                    from @TableB b 
                    where b.name not in (select name from @TableA a where a.id = c.id)
    
         order by NEWID()
                   )
    from @tableC c
    select *
    from @tableC
    

    SQL Server 2012: JOIN 3 tables for a condition

2 个答案:

答案 0 :(得分:0)

在执行上述代码之前清理@tableC:

declare @tableD table (id int, name varchar(2))

insert into @tableD
select distinct * from @tableC

delete from @tableC

insert into @tableC
select * from @tableD

update c
    set Name = (select top 1 b.name
                from @TableB b 
                where b.name not in (select name from @TableA a where a.id = c.id)

     order by NEWID()
               )
from @tableC c
select *
from @tableC

这可能有一种更优雅的方式,但如果@tableC中没有很多行,这是一种快捷方式。

答案 1 :(得分:0)

我不确定随机性是否是必需的。我去了一个非随机解决方案:

; with IDs as (
    select distinct id from @tableA
), AllPossible as (
    select i.id,b.name from IDs i cross join @tableB b
), RemoveExisting as (
    select ap.id,ap.name,ROW_NUMBER() OVER (PARTITION BY ap.id ORDER BY ap.name) rn
    from AllPossible ap left join @tableA a on ap.id = a.id and ap.name=  a.name
    where a.id is null
), COrdered as (
    select id,name,ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) rn
    from @tableC
)
update c
    set name = re.name
from
    Cordered c
        inner join
    RemoveExisting re
        on
            c.id = re.id and
            c.rn = re.rn

希望CTE的名称能给出我对这个问题的看法的线索。

如果要求随机性,则应在接近第一个ROW_NUMBER()表达式的位置引入(在ORDER BY子句中)。