如何在考虑第三个因素的同时删除在两个非主键列中具有相同值的记录?

时间:2021-06-29 04:44:43

标签: sql sql-server

这是带有示例数据的 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

2 个答案:

答案 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

相关问题