如何获取在同一字段中具有相同Id但不同值的行的列表

时间:2015-09-07 10:43:46

标签: sql sql-server

我一直在玩关于重复的不同查询,但这不是我真正需要的。我确实需要一个重复列表,但另一列中的值不同。

我正在尝试在SQL Server 2012中执行此操作。

我需要获取一个“重复”行的列表,其中DocId是相同的,但它们在表中有不同的PoId。

AuditId|DocMasterId|PoNumber
2224   |105        |11111
2374   |105        |11111
2574   |105        |11112
2624   |106        |232323
2874   |106        |242424

基于上述内容的查询应返回

105 106

但理想情况下,如果我可以根据相同的DocMasterId列出每个不同采购订单的第一个和最后一个条目,那将是理想的解决方案,所以我最终会

AuditId|DocMasterId|PoNumber
2224   |105        |11111
2574   |105        |11112
2624   |106        |232323
2874   |106        |242424

关于如何在SQL中实现这一点的任何想法?

感谢。

更新:

我应该澄清一下,我只想列出有PONumber设置的行,我希望我的结果按DocMasterId排序。

根据Tim的回答,最终结果如下:

WITH CTE AS
(
    SELECT AuditId, DocMasterId, PoNumber,
    RN_ASC  = ROW_NUMBER() OVER (PARTITION BY DocMasterID ORDER BY 
    PoNumber ASC),
    RN_DESC = ROW_NUMBER() OVER (PARTITION BY DocMasterID ORDER BY 
    PoNumber DESC),
    CNT = COUNT(*) OVER (PARTITION BY DocMasterID)
FROM dbo.MyTable
WHERE PONumber IS NOT NULL
)
SELECT AuditId, DocMasterId, PoNumber
FROM CTE
WHERE CNT >= 2
AND (RN_ASC = 1 OR RN_DESC = 1)
ORDER BY DocMasterId

4 个答案:

答案 0 :(得分:2)

select AuditId, DocMasterId, PoNumber 
from ( select *,  ROW_NUMBER() OVER (PARTITION BY DocMasterId, PoNumber ORDER BY DocMasterId ASC) as a from tablename ) abc 
where a =1

我使用DocMasterId和PoNumber创建了一个分区列,它将为DocMasterId,PoNumber的每个相同值重复Row_Number。然后我使用条件a = 1

删除了重复记录

答案 1 :(得分:1)

这种方法使用排名函数和CTE:

WITH CTE AS
(
    SELECT AuditId, DocMasterId, PoNumber,
      RN_ASC  = ROW_NUMBER() OVER (PARTITION BY DocMasterID ORDER BY PoNumber ASC),
      RN_DESC = ROW_NUMBER() OVER (PARTITION BY DocMasterID ORDER BY PoNumber DESC),
      CNT = COUNT(*) OVER (PARTITION BY DocMasterID)
    FROM dbo.TableName
)
SELECT AuditId, DocMasterId, PoNumber
FROM CTE
WHERE CNT >= 2
AND (RN_ASC = 1 OR RN_DESC = 1)
ORDER BY DocMasterId

Demo

根据您的评论更新NULL中的PoNumber值应排除在外,不计入CNT

WITH CTE AS
(
    SELECT AuditId, DocMasterId, PoNumber,
      RN_ASC  = ROW_NUMBER() OVER (PARTITION BY DocMasterID 
                                   ORDER BY CASE WHEN PoNumber IS NULL THEN 1 ELSE 0 END ASC,
                                            PoNumber ASC),
      RN_DESC = ROW_NUMBER() OVER (PARTITION BY DocMasterID ORDER BY PoNumber DESC),
      CNT = SUM(CASE WHEN PoNumber IS NOT NULL THEN 1 END) OVER (PARTITION BY DocMasterID)
    FROM dbo.TableName
)
SELECT AuditId, DocMasterId, PoNumber
FROM CTE
WHERE CNT >= 2
AND (RN_ASC = 1 OR RN_DESC = 1)
ORDER BY DocMasterId

Demo ,您的样本数据无法正确返回任何记录。

答案 2 :(得分:0)

如果您的数据库支持Window功能,请尝试使用

;WITH cte
     AS (SELECT Row_number()OVER(partition BY DocMasterId
                    ORDER BY AuditId DESC) a_rn,
                Row_number()OVER(partition BY DocMasterId
                    ORDER BY AuditId )     d_rn,
                *
         FROM   Yourtable)
SELECT AuditId,
       DocMasterId,
       PoNumber
FROM   cte
WHERE  a_rn = 1 or D_rn =1

答案 3 :(得分:0)

只需GROUP BY

select min(AuditId), DocMasterId, PoNumber
from tablename
group by DocMasterId, PoNumber