T-SQL选择至少有一列具有值的重复行

时间:2014-04-22 13:52:53

标签: sql sql-server tsql

我有一个数据库表如下:

ProductDetails
-----------------
ProductDetailsID int
ProductIdentifier VARCHAR (20)
ProductID int
ProductFile VARCHAR(255)
ProductAvailability char(2)
RightsCountry varchar(MAX)
Deleted bit

最近平台上有一个错误,允许大量重复。所以我可以有多个ProductDetails条目,这些条目对于ProductDetailsID(PK)和ProductFile是相同的EXCEPT(由于某种原因,这是重复的没有插入文件)。

我需要编写一个T-SQL脚本来查找这些重复项,以便删除它们(检查后)。

我在网上找到了这个,这很棒。它为ProductIdentifier提供了几条记录和重复数。

SELECT pd.ProductIdentifier, COUNT(pd.ProductIdentifier) AS NumOccurrences
FROM dbo.ProductDetails pd
GROUP BY pd.ProductIdentifier
HAVING ( COUNT(pd.ProductIdentifier) > 1 )

问题是,其中一些记录应该保留。我需要选择具有重复ProductIdentifier的ProductDetail记录,其中至少有一个重复项具有FileName,而所有其他列完全相同。例如,如果我有如下数据集:

ProductDetailsID | ProductIdentifier | ProductID | ProductFile | ProductAvailability | RightsCountry | Deleted
123 | 567890 | 12 | filename.png | 20 | AU CX CC CK HM NZ NU NF TK | 0
124 | 567890 | 12 | (NULL) | 20 | AU CX CC CK HM NZ NU NF TK | 0
125 | 567890 | 12 | (NULL) | 20 | AU CX CC CK HM NZ NU NF TK | 0

我需要返回ProductDetailsID 124和125,因为这些是要删除的。我很感激任何指导或链接到示例或任何帮助!

3 个答案:

答案 0 :(得分:1)

create view rows_to_delete
as
select *
from (
    select *, 
    row_number() over(partition by ProductIdentifier order by ProductFile desc, ProductDetailsID) as rn
    from t
) x
where rn > 1
and ProductFile is null

答案 1 :(得分:1)

这有效并且是滥用分区窗口函数的一种厚颜无耻的方式:

declare @ProductDetails table(
ProductDetailsID int not null,
ProductIdentifier VARCHAR(20) not null,
ProductID int not null,
ProductFile VARCHAR(255) null,
ProductAvailability char(2) not null,
RightsCountry varchar(MAX) not null,
Deleted bit not null
)

insert into @ProductDetails(ProductDetailsID,ProductIdentifier,ProductID,
             ProductFile,ProductAvailability,RightsCountry,Deleted) values
(123,567890,12,'filename.png',20,'AU CX CC CK HM NZ NU NF TK',0),
(124,567890,12,NULL,20,'AU CX CC CK HM NZ NU NF TK',0),
(125,567890,12,NULL,20,'AU CX CC CK HM NZ NU NF TK',0)

;With FillInFileNames as (
    select *,
    MAX(ProductFile) OVER (PARTITION BY ProductIdentifier,ProductID,
                                    ProductAvailability,RightsCountry,Deleted)
       as AnyFileName
    from @ProductDetails
)
select * from FillInFileNames
where ProductFile is null and AnyFileName is not null

如果至少有一个输入值不是NULL,那么聚合函数永远不会返回NULL

结果:

ProductDetailsID ProductIdentifier    ProductID   ProductFile                                                                                                                                                                                                                                                     ProductAvailability RightsCountry                                                                                                                                                                                                                                                    Deleted AnyFileName
---------------- -------------------- ----------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
124              567890               12          NULL                                                                                                                                                                                                                                                            20                  AU CX CC CK HM NZ NU NF TK                                                                                                                                                                                                                                       0       filename.png
125              567890               12          NULL                                                                                                                                                                                                                                                            20                  AU CX CC CK HM NZ NU NF TK                                                                                                                                                                                                                                       0       filename.png

对于OP来说,观察我的脚本的顶部并不比他们问题中提供的表格信息和样本数据更多也可能是有益的 - 除了我的实际上是可运行的

将来可能值得考虑以这种方式编写样品,因为这样可以立即复制和放大样品。从您的问题粘贴到查询窗口。

答案 2 :(得分:0)

以下查询首先获取计数,然后过滤那些字段与带有fileName的条目匹配的记录。

WITH counts as
(
SELECT 
    ProductDetailsID
    , ProductIdentifier
    , ProductID 
    , ProductFile 
    , ProductAvailability 
    , RightsCountry 
    , Deleted
    , COUNT(*) as cnt_files
FROM
    dbo.ProductDetails pd
GROUP BY 
    ProductDetailsID
    , ProductIdentifier
    , ProductID 
    , ProductFile 
    , ProductAvailability 
    , RightsCountry 
    , Deleted
)
SELECT
    c1.*
FROM
    counts c1
INNER JOIN counts c2
ON c1.ProductIdentifier = c2.ProductIdentifier
AND c1.ProductID = c2.ProductID
AND c1.ProductFile = c2.ProductFile
AND c1.ProductAvailability = c2.ProductAvailability
AND c1.RightsCountry = c2.RightsCountry
AND c1.Deleted = c2.Deleted
WHERE ProductFile is NULL;