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

vh0rcniy  于 2023-01-08  发布在  SQL Server
关注(0)|答案(2)|浏览(170)

我有一个数据集,其中某些列的值匹配,但其余列的值不匹配。我需要删除较低级别的子类别(级别2、级别3和级别4)"IS NOT NULL",但其对应的"重复合作伙伴"(按[子类别级别1 ID]、[产品类别]和[产品名称]分组)具有相同的较低级别子类别-"IS NULL"。根据下表,我需要删除ID 2,4、6和9(见红色字体突出显示部分)。
我已经尝试了Dense_Rank,Rank和Row_Number函数,但是没有得到我想要的输出。也许我需要使用它们的组合...
例如:行ID 1和2按[产品类别]、[产品名称]、[类别级别1]重复。"类别级别1"只是"产品类别"的ID。需要删除行ID 2,因为其对应的重复伙伴行ID 1没有分配"类别级别3",而行ID 2有。相同的逻辑适用于行ID 9和10,但此时行ID9具有"类别级别2",而行10没有。如果两个副本(行ID1和2)都将具有分配的"类别级别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
krugob8w

krugob8w1#

如果我没理解错的话,你的逻辑如下:
对于每个唯一的SubCategory Level 1Product CategoryProduct Name组合,您希望返回填充的SubCategory级别数据量最少的行。
在相关字段上使用快速dense_rankpartitions,您可以将具有较少子类别级别的行order设置为1。行2469现在应该是唯一返回的行。

;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,并添加一些应首先选择的替代条件。

1qczuiv0

1qczuiv02#

这个帖子帮助我理解了一种不同的删除重复日期的方法。我想感谢最初的贡献者。但是我注意到最终的解决方案是不完整的。最初的贡献者希望结果返回RowId的2,4,6,9,但是ToInclude!= 1过滤器不允许这样做。我正在添加代码,通过添加where〉来完成查询1个过滤器,它将产生预期的结果。请参见下面的代码:

;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

这将返回:
Results Table of Code

相关问题