左连接重复

时间:2015-05-20 20:02:45

标签: sql-server left-join duplicate-removal

这是一个SQL Server问题。

我正在连接同一个数据库中的三个表,并不断获取重复值。表REF_Plan_Dictionary和REF_Plan_Assign_Default将自行生成重复项,因为某些列将引用其他列中的多个子选项。表dev_OUT_MasterEmp只会为每个EmpID生成一条记录。

查询的目的是使用M.EmpID并将来自其他两个表的信息与此信息进行匹配。重复项是EmpID重复多次但所有信息只匹配一次的地方。这意味着我提到的子选项没有显示,因为其他两个表正确匹配。所以这不是匹配,而是相同的信息是重复的。

如何摆脱重复?

SELECT M.EmpId
      ,EmpName
      ,[UserId]
      ,PA.Plan_Dict_Id
      ,m.Job_Code
      ,Dept_Num
      ,PayGroup
      ,D.Plan_Name
      ,Plan_Desc
      ,M.[File_Nbr]
      ,[Mgr_EmpId]
      ,[Work_Location]
      ,[Emp_Tenure]
      ,[Emp_Status]
      ,[Plan_Eligibility]
      ,M.[Function_Role_Code]
      ,[Hire_Date]
      ,[Job_Entry_Date]
      ,[Term_Date]
      ,[Dept_Num]
      ,[TeamID]
      ,[CCGroup]
      ,[Channel]
      ,[Organization]
      ,[Hourly_Rate]
      ,[HC]
  FROM [Compensation].[dbo].[dev_OUT_MasterEmp] M
  left join Compensation..REF_Plan_Dictionary D on M.Plan_Id = D.Plan_Dict_Id
  left join Compensation..REF_Plan_Assign_Default PA on M.Plan_Id = PA.Plan_Dict_Id

这是我的结果的一个例子: enter image description here

这是表REF_Plan字典: enter image description here

这是表REF_Plan_Assign_Default: enter image description here

2 个答案:

答案 0 :(得分:1)

这是基本计划:

SELECT EMP.*, PL.Plan_NAME , PL.Plan_DESC, 
MAP.Job_Code, MAP.PayGroup
FROM [Compensation].[dbo].[dev_OUT_MasterEmp] EMP
JOIN (
  SELECT M.EMPID, MAX(PA.Plan_Dict_Id) AS M_PLAN_ID, 
  MAX(PA.JobCode) AS Job_Code, MAX(PA.PayGroup) AS PayGroup
  FROM [Compensation].[dbo].[dev_OUT_MasterEmp] M
  LEFT JOIN Compensation..REF_Plan_Assign_Default PA
  ON M.PLAN_ID = PA.Plan_Dict_Id
  GROUP BY M.EMPID
) MAP
ON MAP.EMPID= EMPS.EMPID 
JOIN Compensation..REF_Plan_Dictionary PL
ON MAP.M_PLAN_ID = PL.PLAN_DICT_ID

请修改输出列以满足您的需求。

答案 1 :(得分:0)

避免不必要的重复记录的最佳方法是从头开始计划您认为重复的内容。换句话说,你想要每个员工ID一个记录,或者你想要一个记录(员工,用户帐户)......等等。一旦你确定了你想要的输出的唯一键,那么你构建你的查询周围通过确保在加入该键时,连接的两边只有1比1匹配。

因此,例如,假设您每个员工ID只需要一条记录。您可以从employee表开始,因为这是此表的关键。然后,您加入它的每个表,您必须确保每个员工ID中只有一个记录。您可以使用包含group by的子查询来确保这一点。如下所示:

Select ...
from employees
join
    (Select employeeid, sum(field1), max(field2)...
    from employeedetail
    group by employeeid
    ) employeedetails

在您的情况下,您看起来有两种类型的“详细信息”表,而您的员工记录中有一个外键。因此,如果您希望每个员工有一条记录,那么请确保只为两个详细记录的外键值返回一条记录。

select m.*
FROM [Compensation].[dbo].[dev_OUT_MasterEmp] M
left join
     (
     select Plan_Dict_Id, aggregate_function(field1) as field1... etc.
     Compensation..REF_Plan_Dictionary
     group by Plan_Dict_Id
     ) D 
on M.Plan_Id = D.Plan_Dict_Id
left join
     (
     select Plan_Dict_Id, aggregate_function(field1) as field1... etc.
     Compensation..REF_Plan_Assign_Default 
     group by Plan_Dict_Id
     ) PA
on M.Plan_Id = PA.Plan_Dict_Id

在子查询中,您必须在字段(上面的Field1)上使用聚合函数,因为可能存在重复项。例如,可能有一个付款字段,您想知道对此plan_id付款的总金额,然后您将使用sum(Payment)

消除除一条“细节”记录之外的所有记录的另一种方法是过滤。所以也许你只想看到最新的记录。在这种情况下,您将使用过滤器来消除所有重复但您感兴趣的重复项。您的子查询可能如下所示:

select *
from DetailTable 
join (
    select ID, MAX(updated_date) updated_date
    from DetailTable
    group by ID
    ) MaxRecord
on DetailTable.ID = MaxRecord.ID
    and DetailTable.updated_date = MaxRecord.updated_date

此子查询每个ID只会返回一条记录,而且该记录的ID最大updated_date

我无法告诉你应该如何构建你的子查询,因为我无法确切地说出你想要做什么,但一般的想法是从一个表或一些带有连接的表开始你可以保证有一个独特的钥匙。然后,您可以在此之后执行连接和左连接到其他具有相同唯一键的表或子查询。当你掌握了这一点时,你永远不会再有意想不到的重复。