Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 基于相关行中的值更新列_Sql_Sql Server 2008_Sql Update_Rows - Fatal编程技术网

Sql 基于相关行中的值更新列

Sql 基于相关行中的值更新列,sql,sql-server-2008,sql-update,rows,Sql,Sql Server 2008,Sql Update,Rows,在SQLServer2008中,我有一个如下表 AMID TierLevel -------- ------------- 999 GOLD 1000 SILVER 1000 GOLD 1000 PLATINUM 1000 BRONZE 1001

在SQLServer2008中,我有一个如下表

  AMID                TierLevel
 --------            -------------
  999                 GOLD
  1000                SILVER   
  1000                GOLD
  1000                PLATINUM
  1000                BRONZE
  1001                GOLD
  1001                SILVER
  1002                SILVER
  1003                GOLD
现在我想更新这个表,如下所示

  AMID                TierLevel
 --------            -------------
  999                 GOLD
  1000               PLATINUM  
  1000               PLATINUM
  1000               PLATINUM
  1000               PLATINUM
  1001                GOLD
  1001                GOLD
  1002                SILVER
  1003                GOLD
条件是这样的

  • 我希望同一层具有唯一的层值,并且层值应在优先级基础中选择,如

  • 白金
  • 黄金
  • 银币
  • 青铜色
  • 这意味着如果它的层值中存在最高值,则选择该值。正如我在第二张表中所示,白金1000英镑,黄金1001英镑

请帮我做这个

谢谢,

Harry

我会使用一个临时表来存储每一层的排名:

DECLARE @Rank TABLE (ID INT NOT NULL PRIMARY KEY, Name VARCHAR(10) NOT NULL)
INSERT @Rank VALUES (1, 'PLATINUM'), (2, 'GOLD'), (3, 'SILVER'), (4, 'BRONZE')

;WITH T AS
(   SELECT  AMID, TierLevel, MIN(ID) OVER(PARTITION BY AMID) [MinID]
    FROM    #T
            INNER JOIN @Rank
                ON Name = TierLevel
)
UPDATE  T
SET     TierLevel = Name
FROM    T
        INNER JOIN @Rank
            ON ID = MinID
WHERE   TierLevel <> Name

谢谢Gareth,这是我桌子上的gr8,我想问你一个小问题。这会更新表中的所有行还是只更新需要更改值的行??因为它显示的是从我的200k行表中更新的190k行。。!!它会更新所有行,所以听起来你有一些行不是青铜、银、金或白金!正如Aaron所建议的,我在更新语句中添加了一个where子句。@GarethD不,我不认为有“一些行不是青铜、银、金或白金的”-没有where子句的更新语句根本不关心,如果AMID有800行都是银的,它会将它们全部更新为silver,即使它们不应该是更新的候选对象,因为它们已经包含了正确的值。@AaronBertrand完全正确,没有where子句,所有行都将被更新,无论是否必要。因此,如果表包含200k行,并且没有where子句,只更新了190k行,那么其他10K行会发生什么情况?这表明它们被Name=TierLevel上的
内部连接排除在外,这意味着中间不是青铜、银、金或白金。这是我能看到行数减少的唯一方法,没有where子句(请记住,我在关于行数更新的评论之后才将其添加到答案中)。所以不是青铜、银、金或白金。。。我意识到这是一个轻微的灰色区域,因为如果你做
SELECT*FROM T WHERE AMID NOT IN('brown','Silver','Gold','Platinum')
它不会返回这些缺失的行,但我只是试图解释10k行的差异。我想我应该说得更清楚些。@harry那你为什么接受它,然后不接受它,然后接受另一个答案,因为我帮了忙才是正确的?哎哟。。!对不起,伙计,我想我可以把这两个都标记为答案,首先我点击了你的,然后点击了另一个,可能是第二个。。我没有注意到(
CREATE TABLE #T (AMID INT, TierLevel VARCHAR(10))
INSERT #T VALUES 
    (999, 'GOLD'), 
    (1000, 'SILVER'), 
    (1000, 'GOLD'), 
    (1000, 'PLATINUM'), 
    (1000, 'BRONZE'),
    (1001, 'GOLD'),
    (1001, 'SILVER'),
    (1002, 'SILVER'),
    (1003, 'GOLD')
DECLARE @amid TABLE (Amid INT, TierLevel VARCHAR(20));

INSERT @amid VALUES
(999 ,'GOLD'),
(1000,'SILVER'), (1000,'GOLD'),   (1000,'PLATINUM'), (1000,'BRONZE'),
(1001,'GOLD'),   (1001,'SILVER'),
(1002,'SILVER'), (1003,'GOLD');

;WITH [priority](r, n) AS
(
    SELECT 1, 'PLATINUM'
    UNION ALL SELECT 2, 'GOLD'
    UNION ALL SELECT 3, 'SILVER'
    UNION ALL SELECT 4, 'BRONZE'
),
per_amid(amid, h) AS
(
    SELECT a.amid, MIN(p.r)
      FROM @amid AS a
      INNER JOIN [priority] AS p
      ON a.TierLevel = p.n
      GROUP BY a.amid
)
UPDATE a
  SET TierLevel = p.n
  FROM @amid AS a
  INNER JOIN per_amid AS pa
  ON a.Amid = pa.amid
  INNER JOIN [priority] AS p
  ON pa.h = p.r
  -- added where clause to address question brought up on other answer
  WHERE a.TierLevel <> p.n;

SELECT Amid, TierLevel FROM @amid;
Amid  TierLevel
----  ---------
999   GOLD
1000  PLATINUM
1000  PLATINUM
1000  PLATINUM
1000  PLATINUM
1001  GOLD
1001  GOLD
1002  SILVER
1003  GOLD