我的SELECT查询的准确性

时间:2014-09-05 15:56:58

标签: sql sql-server select duplicates

我主要发布此内容以检查我的逻辑。查询运行正常,但我希望得到更有经验的一组眼睛,以确保我正确地构建它。

此查询的目的是查找所有重复的PaperPersonID值,并将它们与负责创建重复对象的客户端DisplayNameUserName相关联。

此查询返回99 rows

SELECT  DISTINCT 
        AO.DisplayName AS AODisplayName,
        AD.UserName AS ADUserName,
        GP.PaperPersonID,
        AD.OperationType

  FROM <Redacted>.[AuditedObjectWeakReference] AO

  INNER JOIN <Redacted>.GenericPerson GP
  ON GP.Oid = AO.GuidId

  INNER JOIN <Redacted>.AuditDataItemPersistent AD
  ON AO.Oid = AD.AuditedObject

  WHERE PaperPersonID IS NOT NULL
  AND AD.OperationType = 'ObjectCreated'
  AND PaperPersonID IN (
        SELECT DISTINCT PaperPersonID
        FROM GenericPerson

        WHERE PaperPersonID IS NOT NULL

        GROUP BY PaperPersonID
        HAVING COUNT(*) >1)


  GROUP BY AO.DisplayName, AD.UserName, GP.PaperPersonID, AD.OperationType
  ORDER BY PaperPersonID, UserName, DisplayName 

同样,这似乎工作正常,但我没有真正的基线来比较,所以我不知道预期的结果是什么。我只针对ID字段运行查询,并返回53 rows

USE <Redacted>

SELECT PaperPersonID
FROM GenericPerson

WHERE PaperPersonID IS NOT NULL

GROUP BY PaperPersonID
HAVING COUNT(PaperPersonID) >1

然而,第一个查询显示每个重复的条目,而第二个查询显示每个重复的条目一次,所以我认为我在99 rows

的球场

1 个答案:

答案 0 :(得分:1)

重复检查的一个好方法是使用ROW_NUMBER()函数,也许COUNT()函数使用OVER()

;with cte AS (SELECT  *,ROW_NUMBER() OVER(PARTITION BY PaperPersonID ORDER BY PaperPersonID) AS RN
                       ,COUNT(*) OVER(PARTITION BY PaperPersonID) AS Dup_CT
              FROM <Redacted>.[AuditedObjectWeakReference])
 SELECT *
 FROM cte
 WHERE Dup_CT > 1

这不会过滤第二个查询中GROUP BY / HAVING之类的记录,并对重复项进行编号。如果您将其放入cte,则可以使用WHERE RN = 1进行过滤。这通常比使用PaperPersonID IN ()更有效。

ROW_NUMBER()函数为每一行分配一个数字。 PARTITION BY是可选的,但用于为该组中的每个值开始编号,即:如果您PARTITION BY PaperPersonID,那么对于每个唯一的PaperPersonID值,编号将从1开始。ORDER BY当然用于定义计数应该如何进行,并且在ROW_NUMBER()函数中是必需的。

COUNT()SUM()等聚合函数也可以使用OVER()PARTITION BY的运行方式相同,ORDER BY不需要。