这是带有示例数据的 sqlfiddle 的链接:http://sqlfiddle.com/#!18/d8d552/3
我正在尝试从名称和颜色具有相同值的行中删除 1 行。如果他们的分数相同,那么删除哪一个都没有关系。如果这些行的分数不同,那么我想删除分数较低的行。
我正在使用内部联接将其归结为正确的行(但有一个额外的行,该行的分数与我想保留其中之一的分数相同),但我很难区分分数。
我尝试过的另一条路线是使用第二个查询获取我想要删除的确切行,但是我似乎无法获取 ItemID,因为它不是聚合函数或 GROUP BY 的一部分。使用函数 ROW_NUMBER() 有助于获取正确的行,但很难获取要删除的 ID。
我想删除 ItemIds 1 和 9,然后是 (2,4) 中的 1 和 (6,8) 中的 1
ItemID | 姓名 | 颜色 | 得分 |
---|---|---|---|
1 | asdf | 绿色 | 5 |
2 | asdf | 蓝色 | 4 |
3 | asdf | 绿色 | 6 |
4 | asdf | 蓝色 | 4 |
5 | asdf | 黄色 | 0 |
6 | qwer | 绿色 | 3 |
7 | qwer | 蓝色 | 3 |
8 | qwer | 绿色 | 3 |
9 | qwer | 蓝色 | 2 |
10 | qwer | 黄色 | 0 |
这是我尝试过的一些 SQL,它让我很接近:
SELECT I.*
FROM Items I
INNER JOIN
(SELECT name, color, MIN(score) AS ms
FROM Items
GROUP BY name, color
HAVING COUNT(*) > 1) s ON I.name = s.name
AND I.color = s.color
AND I.score = ms
ORDER BY I.ItemID
GO
SELECT
name, color, MIN(score) AS minScore,
ROW_NUMBER() OVER (PARTITION BY name, color
ORDER BY MIN(score)) AS rn
FROM Items
GROUP BY name, color
HAVING COUNT(*) > 1
ORDER BY name
我相信@Susang 的回答比我的好。这是一个指向它工作的小提琴的链接:http://sqlfiddle.com/#!18/d8873/5
答案 0 :(得分:0)
您可以使用 CTE 如下:
CREATE TABLE #test(ItemID INT, name varchar(50), color varchar(50), score INT)
INSERT INTO #test(ItemID, name, color, score) VALUES
(1, 'asdf', 'green', 5),
(2, 'asdf', 'blue', 4),
(3, 'asdf', 'green', 6),
(4, 'asdf', 'blue', 4),
(5, 'asdf', 'yellow', 0),
(6, 'qwer', 'green', 3),
(7, 'qwer', 'blue', 3),
(8, 'qwer', 'green', 3),
(9, 'qwer', 'blue', 2),
(10, 'qwer', 'yellow', 0)
;WITH recDelete AS (
SELECT
rnk = ROW_NUMBER() OVER (PARTITION BY name, color ORDER BY score DESC),
ItemID
FROM #test
)
DELETE FROM recDelete WHERE rnk > 1
答案 1 :(得分:0)
使用可更新的 CTE!这很简单:
WITH todelete AS (
SELECT i.*
ROW_NUMBER() OVER (PARTITION BY name, color ORDER BY score DESC) as seqnum
FROM items i
)
DELETE todelete
WHERE seqnum > 1;
不需要JOIN
。