从内部查询更新表只使用第一个值

时间:2013-11-04 17:26:23

标签: sql sql-server-2008

我有一个像这样的SQL表:

表用户

  Id         Name         Country          rank            total
+----+---------------+---------------+-----------------+-------------+
  1          John          Canada                           
  2          Kate          Canada                           
  3          Mark          Canada                           
  4          Max           Argentina                        
  5          Sam           Argentina                        
  6          Stacy         China                            
  7          Ken           China                            
  8          jack          China                            
  9          Don           China                           

我想填写ranktotal值,如下所示:

  Id         Name         Country          rank            total
+----+---------------+---------------+-----------------+-------------+
  1          John          Canada           1                3
  2          Kate          Canada           2                3
  3          Mark          Canada           3                3
  4          Max           Argentina        1                2
  5          Sam           Argentina        2                2
  6          Stacy         China            1                4
  7          Ken           China            2                4
  8          jack          China            3                4
  9          Don           China            4                4

总数基本上是每个国家/地区的总数,排名只是该国家的1,2,3,4 ....(每个国家重置一次)。

为此,我尝试了以下方法:

update Users
 set rank=u.tempRank, total=u.tempTotal
from
(select *,
         row_number() over (partition by [Country] order by newid()) as tempRank,
         count(*) over (partition by [Country]) as tempTotal
  from Users) as u

然而,ranktotal都等于第一个tempRank和tempTotal,我得到了这个表

  Id         Name         Country          rank            total
+----+---------------+---------------+-----------------+-------------+
  1          John          Canada           1                3
  2          Kate          Canada           1                3
  3          Mark          Canada           1                3
  4          Max           Argentina        1                3
  5          Sam           Argentina        1                3
  6          Stacy         China            1                3
  7          Ken           China            1                3
  8          jack          China            1                3
  9          Don           China            1                3

如果我尝试单独调试内部查询:

select *,
         row_number() over (partition by [Country] order by newid()) as tempRank,
         count(*) over (partition by [Country]) as tempTotal
  from Users

没有更新,只是选择,我得到了正确的结果:

  Id         Name         Country          tempRank        tempTotal
+----+---------------+---------------+-----------------+-------------+
  1          John          Canada           1                3
  2          Kate          Canada           2                3
  3          Mark          Canada           3                3
  4          Max           Argentina        1                2
  5          Sam           Argentina        2                2
  6          Stacy         China            1                4
  7          Ken           China            2                4
  8          jack          China            3                4
  9          Don           China            4                4

所以问题在于更新,它只取第一行并基于它更新所有表。

如何迭代每一行来更新它?

2 个答案:

答案 0 :(得分:1)

尝试像这样update

with toupdate (
    select *,
           row_number() over (partition by [Country] order by newid()) as tempRank,
           count(*) over (partition by [Country]) as tempTotal
    from Users
   )
update toupdate
   set rank = tempRank, total = tempTotal;

这利用了SQL Server的一个非常好的功能,您可以在其中更新和“可更新的CTE”。

您的查询的问题是您有两个未加入的表。我想你可以简化它:

update u
   set rank=u.tempRank, total=u.tempTotal
   from (select *,
                row_number() over (partition by [Country] order by newid()) as tempRank,
                count(*) over (partition by [Country]) as tempTotal
         from Users
        ) u;

否则,您需要将它们连接在一起:

update users
   set rank=u.tempRank, total=u.tempTotal
   from (select *,
                row_number() over (partition by [Country] order by newid()) as tempRank,
                count(*) over (partition by [Country]) as tempTotal
         from Users
        ) u
   where users.id = u.id;

答案 1 :(得分:0)

试试这个:

Update u set
    rank = (select count(*) from users
            where country = u.country 
               and id <= u.Id),
    total = (Select count(*) from users
             where country = u.country)
From users u