我主要发布此内容以检查我的逻辑。查询运行正常,但我希望得到更有经验的一组眼睛,以确保我正确地构建它。
此查询的目的是查找所有重复的PaperPersonID
值,并将它们与负责创建重复对象的客户端DisplayName
和UserName
相关联。
此查询返回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
答案 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
不需要。