我有下表将用户与技能联系起来:
DECLARE @tbl_UsersSkills TABLE (
userId int NOT NULL,
skillId int NOT NULL,
UNIQUE NONCLUSTERED (userId, skillId)
);
INSERT INTO @tbl_UsersSkills
(userId, skillID)
VALUES
(100, 1),(100,2),(100,3),(100,4),(200,1),(200,3),(200,4);
在选择所有行时,它提供以下结果集:
userId skillId
----------- -----------
100 1
100 2
100 3
100 4
200 1
200 3
200 4
已经确定技能1实际上与技能2相同,因此我们需要将1和1组合在一起。 2在一起,只留下2个。
我想我可以抓住1个用户的技能,然后删除它们并重新插入它们,但它似乎是一个软糖,并会增加身份值(在真实的桌子上),并认为MERGE
是一个更迷人的选择。
我需要进入这个结果集:
userId skillId
----------- -----------
100 1 <-- removed because (100,2) exists already
100 2
100 3
100 4
200 1 <-- updated to be (200, 2)
200 3
200 4
这是我的尝试,但是我收到一条错误,即MERGE语句多次修改同一行。
Msg 8672,Level 16,State 1,Line 11 MERGE声明试图 多次更新或删除同一行。这发生在a 目标行匹配多个源行。 MERGE声明不能 多次更新/删除目标表的同一行。提炼 ON子句,以确保目标行最多匹配一个源行, 或使用GROUP BY子句对源行进行分组。
任何人都可以完善它吗?
WITH cte AS (SELECT userId, skillId FROM @tbl_UsersSkills WHERE (skillId IN (@s1, @s2)))
MERGE
@tbl_UsersSkills tgt
USING
cte src
ON
(tgt.skillId = src.skillId)
WHEN NOT MATCHED BY TARGET THEN
INSERT (skillId) VALUES (@s2)
WHEN MATCHED THEN UPDATE SET
tgt.skillId = @s2;
答案 0 :(得分:1)
我猜这可能不是常见的事情。所以如果它有效,它就有效。我认为不是使用MERGE,而是只使用技能1(非技能2)将技能2更新为UserId,然后删除任何技能为1的行。
DECLARE @tbl_UsersSkills TABLE (
userId int NOT NULL,
skillId int NOT NULL,
UNIQUE NONCLUSTERED (userId, skillId)
);
INSERT INTO @tbl_UsersSkills
(userId, skillID)
VALUES
(100, 1),(100,2),(100,3),(100,4),(200,1),(200,3),(200,4);
UPDATE @tbl_UsersSkills
SET skillID = 2
WHERE skillID = 1
AND userId NOT IN (SELECT DISTINCT userID FROM @tbl_UsersSkills WHERE skillId = 2)
DELETE
FROM @tbl_UsersSkills
WHERE skillId = 1
SELECT *
FROM @tbl_UsersSkills
结果:
userId skillId
----------- -----------
100 2
100 3
100 4
200 2
200 3
200 4
答案 1 :(得分:1)
尝试这两种陈述方法:
DELETE @tbl_UsersSkills
FROM @tbl_UsersSkills u1
WHERE u1.skillId = 1 and EXISTS
(SELECT * FROM @tbl_UsersSkills u2 WHERE u2.userId = u1.userId AND u2.skillId = 2)
UPDATE @tbl_UsersSkills
SET skillId = 2
WHERE skillId = 1