【问题标题】:SQL Update a Single Row Multiple Times (Row by Row)SQL 多次更新单行(逐行)
【发布时间】:2014-10-26 06:10:56
【问题描述】:

我在 tsql 中工作,遇到一个问题,我需要根据多个条件对单行进行多次更新。

  1. 按升序排列
  2. 如果该列为 NULL,无论 Rank 是多少,我都需要更新它。
  3. 如果排名相同,我需要按照 T2_ID 的顺序更新。
  4. 我需要它来使用最后更新的输出。

我尝试过使用下面的更新语句,但它只执行第一次更新,其余的被忽略。这是我正在使用的数据集和所需结果的示例。

提前致谢!

update a
set Middle = case when a.Rank_ >= b.Rank_ OR a.Middle IS NULL then ISNULL(b.Middle, a.Middle) end,
    LName = case when a.Rank_ >= b.Rank_ OR a.Lname IS NULL then ISNULL(b.LName, a.LName) end,
    Rank_ = case when a.Rank_ >= b.Rank_ then b.Rank_ end
from #temp1 a
inner join #temp2 b on a.fname = b.fname
where 
    b.T2_ID in (select top 100% T2_ID from #temp2 order by T2_ID asc)

表 1

Fname   Middle  Lname   Rank_
------------------------------
John    NULL    NULL    2

表2

 T2_ID  Fname   Middle  Lname   Rank_
 --------------------------------------
    1   John    Mike    Doe      3
    2   John    NULL    Smith    1
    3   John    NULL    Davis    1

想要的结果:

Fname   Middle  Lname   Rank_
-------------------------------
John    Mike    Davis   1

【问题讨论】:

  • 我不明白更新Rank_列的规则。你能澄清一下吗?
  • 您有使用 CTE 的示例吗?我试过了,但我无法让它工作。
  • 我还更新了 Rank_ 规则,但本质上如果 rcd 的值低于正在更新的 rcd,则更新该字段,否则忽略。
  • 您的联接为#table1 中的每一行返回多行。 UPDATE 必须唯一确定应该更新哪些数据。
  • 我看不出 John Mike Davis 的 Rank_ 是如何从 2 变为 1。请解释一下。

标签: sql sql-server sql-update common-table-expression


【解决方案1】:

单个 UPDATE 语句只能更新每条记录一次。

因此,如果我理解正确,您想要的结果只是每个 Fname 一条记录,对具有最低排名的每一列使用非空值,如果出现平局,则使用最高 T2_ID?

您可以简单地使用子选择来实现这一点:

SELECT 
    Fname,

    (SELECT TOP 1 Middle FROM #temp1 b
     WHERE Middle IS NOT NULL AND b.Fname = a.Fname
     ORDER BY Rank_, T2_ID DESC) AS Middle

    (SELECT TOP 1 Lname FROM #temp1 b
     WHERE Lname IS NOT NULL AND b.Fname = a.Fname
     ORDER BY Rank_, T2_ID DESC) AS Lname

    (SELECT TOP 1 Rank_ FROM #temp1 b
     WHERE Rank_ IS NOT NULL AND b.Fname = a.Fname
     ORDER BY Rank_, T2_ID DESC) AS Rank_
FROM
    #temp1 a
GROUP BY
    Fname    /* To get one record per Fname */

然后您可以使用此选择的结果更新#temp2

【讨论】:

  • 我了解此查询的逻辑,但它不可能是执行此操作的有效方法。在我的实际查询中,我正在更新 ~10 列。这种方法对数据库来说太重了
  • 在对性能做出任何假设之前,您应该尝试一下。
【解决方案2】:
You also user group by and having 



    create table #temp1(

    fname varchar(10),
    mname varchar(10),
    lname varchar(10),
    rank_ int
)
 create table #temp2(
    t2id int,
    fname varchar(10),
    mname varchar(10),
    lname varchar(10),
    rank_ int
)

insert into #temp1
select 'john',null,null,2 

insert into #temp2
select 1,'john','mike','doe',3 union all 
select 2,'john',null,'smith',1 union all 
select 3,'john',null,'davis',1 


select top 1 fname,(select top 1 mname from #temp2 order by rank_ desc) as mname,lname,min(asrank_) from (
select b.rank_,a.fname,case when a.Rank_ >= b.Rank_ OR a.mname IS NULL then ISNULL(b.mname, a.mname) end as mname,
    case when a.Rank_ >= b.Rank_ OR a.Lname IS NULL then b.LName end as lname,
    case when a.Rank_ >= b.Rank_ then b.Rank_ end asrank_
from #temp1 a
inner join #temp2 b on a.fname = b.fname)tbl group by fname,mname,lname having min(asrank_)=1



drop table #temp2
drop table #temp1

【讨论】:

    猜你喜欢
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 2011-06-03
    • 2010-09-07
    • 1970-01-01
    • 2015-11-11
    • 2021-02-15
    相关资源
    最近更新 更多