Sql 基于相关行中的值更新列
在SQLServer2008中,我有一个如下表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
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