删除 SQL Server 2016 中的部分重复行

Remove Partial Duplicate Rows in SQL Server 2016

我有一个数据集,其中某些列的值匹配,但其余列的值不匹配。我需要删除重复项,其中较低级别的子类别(Level2、Level3 和 Level 4)"IS NOT NULL" 但其对应的 "duplicate partner"(按 [SubCategory Level 1 ID]、[Product Category] ​​和 [Product Name] 分组]) 具有相同的较低级别子类别 - "IS NULL"。根据下面的 table,我需要删除 ID 2、4、6 和 9(请参阅以红色字体突出显示的部分)。

我试过 Dense_Rank、Rank 和 Row_Number 函数与分区依据,但没有给我不满意的输出。也许我需要使用他们的组合...

例如:RowID 1 和 2 与 [Product Category]、[Product Name]、[Category Level 1] 重复。 "Category Level 1" 只是 "Product Category" 的 ID。需要删除 RowID 2,因为它对应的重复伙伴 RowID 1 在 RowID 2 分配时没有分配 "Category Level 3"。相同的逻辑适用于 RowID 9 和 10,但此时 RowID 9 具有 "Category Level 2",而第 10 行没有。如果两个重复项(RowID 1 和 2)都分配了 "Category Level 3",我们就不需要删除它们中的任何一个

IF OBJECT_ID('tempdb..#Category', 'U') IS NOT NULL
  DROP TABLE #Category;
GO

CREATE TABLE #Category 
(
    RowID INT NOT NULL,
    CategoryID INT NOT NULL,
    ProductCategory VARCHAR(100) NOT NULL,
    ProductName VARCHAR(100) NOT NULL,
    [SubCategory Level 1 ID] INT NOT NULL,
    [SubCategory Level 2 ID] INT NULL,
    [SubCategory Level 3 ID] INT NULL,  
    [SubCategory Level 4 ID] INT NULL
);

INSERT INTO #Category (RowID, CategoryID, ProductCategory, ProductName, [SubCategory Level 1 ID], [SubCategory Level 2 ID], [SubCategory Level 3 ID], [SubCategory Level 4 ID])
VALUES 
(1, 111, 'Furniture', 'Table', 200, 111, NULL, NULL),
(2, 234, 'Furniture', 'Table', 200, 234, 123, NULL),
(3, 122, 'Furniture', 'Chair', 200, 122, NULL, NULL),
(4, 122, 'Furniture', 'Chair', 200, 122, 32, NULL),
(5, 12, 'Auto', 'Trucks', 300, 766, 12, NULL),
(6, 3434, 'Auto', 'Trucks', 300, 322, 3434, 333),
(7, 332, 'Auto', 'Sport Vehicles', 300, 332, NULL, NULL),
(8, 332, 'Auto', 'Sport Vehicles', 300, 332, NULL, NULL),
(9, 300, 'Auto', 'Sedans', 300, 231, NULL, NULL),
(10, 300, 'Auto', 'Sedans', 300, NULL, NULL, NULL),
(11, 300, 'Auto', 'Cabriolet', 300, 456, 688, NULL),
(12, 300, 'Auto', 'Cabriolet', 300, 456, 976, NULL),
(13, 300, 'Auto', 'Motorcycles', 300, 456, 235, 334),
(14, 300, 'Auto', 'Motorcycles', 300, 456, 235, 334);


SELECT * FROM #Category; 
-- ADD YOU CODE HERE TO RETURN the following RowIDs: 2, 4, 6, 9

如果我没理解错的话,你的逻辑是这样的:

对于每个唯一的 SubCategory Level 1Product CategoryProduct Name 组合,您希望 return 填充子类别级别数据最少的行。

在相关字段上使用快速 dense_rankpartitions,您可以 order 将子类别级别较少的行设置为 12469 行现在应该是唯一的行 returned.

;with DataToSelect
as
(
    SELECT *,
           DENSE_RANK() OVER(PARTITION BY [ProductCategory], [ProductName], [SubCategory Level 1 ID] 
                    ORDER BY
                        CASE 
                            WHEN [SubCategory Level 4 ID] IS NOT NULL THEN 3
                            WHEN [SubCategory Level 3 ID] IS NOT NULL THEN 2
                            WHEN [SubCategory Level 2 ID] IS NOT NULL THEN 1
                            END) as [ToInclude]
    FROM #Category
)
SELECT *
FROM 
    DataToSelect
WHERE 
    ToInclude != 1
ORDER BY 
    RowID

请记住,如果每个 SubCategory Level 1Product CategoryProduct Name 组合中有两行具有相同的子类别级别,则它们都将包含在内。如果您不想这样做,只需将 dense_rank 换成 row_number 并添加一些应首先选择的替代标准。