2017-10-04 40 views
0

我需要根据两个表和基于自定义条件查找重复项。以下内容决定它是否重复,如果是,则只显示最近的一个:SQL:根据自定义标准查找重复记录

如果员工姓名和所有EmployeePolicy CoverageId(s)完全匹配另一个记录,则认为它是重复的。

--Employee Table 
EmployeeId Name Salary 
543   John 54000 
785   Alex 63000 
435   John 75000 
123   Alex 88000 
333   John 67000 

--EmployeePolicy Table 
EmployeePolicyId EmployeeId CoverageId 
1     543   8888 
2     543   7777 
3     785   5555 
4     435   8888 
5     435   7777 
6     123   4444 
7     333   8888 
8     333   7776 

例如,在示例中的重复以上如下:

EmployeeId Name Salary 
543  John 54000 
435  John 75000 

这是因为它们是在雇员表具有匹配的名称,以及两者都具有唯一的EmployeePolicy表中的CoverageIds完全相同。

注意: EmployeeId 333也与Name = John不匹配,因为他的CoverageID与其他John的CoverageIds不同。

起初,我一直试图通过对记录进行分组并重复计数(*)> 1来找出重复的旧式方式,但后来很快意识到它不起作用,因为在英语中,我的标准定义了重复的SQL的CoverageIDs是不同的,所以它们不被认为是重复的。

通过相同的协议,我想是这样的:

-- Create a TMP table 

INSERT INTO #tmp 
SELECT * 
FROM Employee e join EmployeePolicy ep on e.EmpoyeeId = ep.EmployeeId 

SELECT info.* 
FROM 
(
    SELECT 
     tmp.*, 
     ROW_NUMBER() OVER(PARTITION BY tmp.Name, tmp.CoverageId ORDER BY tmp.EmployeeId DESC) AS RowNum 
    FROM #tmp tmp 
) info 
WHERE 
    info.RowNum = 1 AND 

同样,因为SQL不认为这是重复这是否不起作用。不知道如何将我的英文重复定义翻译成重复的SQL定义。

任何帮助最受赞赏。

+0

用样本数据填充临时表并显示预期结果 –

回答

3

最简单的方法是将策略连接成一个字符串。唉,在SQL Server中很麻烦。这是一套基于集合的方法:

with ep as (
     select ep.*, count(*) over (partition by employeeid) as cnt 
     from employeepolicy ep 
    ) 
select ep.employeeid, ep2.employeeid 
from ep join 
    ep ep2 
    on ep.employeeid < ep2.employeeid and 
     ep.CoverageId = ep2.CoverageId and 
     ep.cnt = ep2.cnt 
group by ep.employeeid, ep2.employeeid, ep.cnt 
having count(*) = cnt -- all match 

这个想法是匹配不同员工的覆盖率。一个简单的标准是覆盖的数量需要匹配。然后,它检查匹配coverage的数量是实际计数。

注意:这会将员工ID对放在一行中。您可以加入雇员表以获取附加信息。

0

我还没有测试过T-SQL,但我相信下面应该给你你正在寻找的输出。

;WITH CTE_Employee 
AS 
(
    SELECT  E.[Name] 
       ,E.[EmployeeId] 
       ,P.[CoverageId] 
       ,E.[Salary] 
    FROM  Employee E 
    INNER JOIN EmployeePolicy P ON E.EmployeeId = P.EmployeeId 
) 
, CTE_DuplicateCoverage 
AS 
(
    SELECT  E.[Name] 
       ,E.[CoverageId] 
    FROM  CTE_Employee E 
    GROUP BY E.[Name], E.[CoverageId] 
    HAVING  COUNT(*) > 1 
) 
SELECT  E.[EmployeeId] 
      ,E.[Name] 
      ,MAX(E.[Salary]) AS [Salary] 
FROM  CTE_Employee E 
INNER JOIN CTE_DuplicateCoverage D ON E.[Name] = D.[Name] AND E.[CoverageId] = D.[CoverageId] 
GROUP BY E.[EmployeeId], E.[Name] 
HAVING  COUNT(*) > 1 
ORDER BY E.[EmployeeId]