2016-12-23 48 views
0

首先,当我开始这个项目看起来很简单。表1中的两个表tbl1_USERMASTERID字段应该从字段tbl2_USERMASTERID表2中更新。在我深入查看表2之后,没有可以用作连接这两个表的唯一ID。匹配表1和表2中的记录的唯一方法是基于FIRST_NAME,LAST_NAME和DOB。所以我必须找到在表1中记录,其中:更新记录SQL?

tbl1_FIRST_NAME equals tbl2_FIRST_NAME 
AND 
tbl1_LAST_NAME equals tbl2_LAST_NAME 
AND 
tbl1_DOB equals tbl2_DOB 

,然后更新USERMASTERID场。我担心这可能会导致一些重复,并且一些用户将以不属于他们的USERMASTERID结束。因此,如果我根据first,last name和dob查找多条记录,则不会更新这些记录。我想跳过并留空。这样我就不会填充无效的USERMASTERID。我不确定解决这个问题的最佳方法是什么,我应该使用SQL还是ColdFusion(我的服务器端语言)?另外如何检测多个匹配记录?

这是我到目前为止有:

UPDATE Table1 AS tbl1 
LEFT OUTER JOIN Table2 AS tbl2 
    ON tbl1.dob = tbl2.dob 
    AND tbl1.fname = tbl2.fname 
    AND tbl1.lname = tbl2.lname 
SET tbl1.usermasterid = tbl2.usermasterid 
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = '' 

这是查询我就开始想检测重复:

SELECT DISTINCT 
    tbl1.FName, 
    tbl1.LName, 
    tbl1.dob, 
    COUNT(*) AS count 
FROM Table1 AS tbl1 
    LEFT OUTER JOIN Table2 AS tbl2 
     ON tbl1.dob = tbl2.dob 
     AND tbl1.FName = tbl2.first 
     AND tbl1.LName = tbl2.last 
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = '' 
    AND LTRIM(RTRIM(tbl1.first)) <> '' 
    AND LTRIM(RTRIM(tbl1.last)) <> '' 
    AND LTRIM(RTRIM(tbl1.dob)) <> '' 
GROUP BY tbl1.FName,tbl1.LName,tbl1.dob 

一些数据经过笔者测试上面的查询:

First Last  DOB Count 
John Cook 2008-07-11 2 
Kate Witt 2013-06-05 1 
Deb  Ruis 2016-01-22 1 
Mike Bennet 2007-01-15 1 
Kristy Cruz 1997-10-20 1 
Colin Jones 2011-10-13 1 
Kevin Smith 2010-02-24 1 
Corey Bruce 2008-04-11 1 
Shawn Maiers 2016-08-28 1 
Alenn Fitchner 1998-05-17 1 

如果有人知道如何防止/跳过更新重复记录或如何改善此查询请让我知道。谢谢。

+0

你可以添加样本数据和预期的结果 –

+0

有选择查询开始。这将使您能够查看将要更新的记录。如果结果看起来不正确,则应用常规故障排除。 –

+0

你可以添加表格模式吗? – McNets

回答

1

你可以检查并避免重复使用匹配with common_table_expression (Transact-SQL)row_number()一起,就像这样:

with cte as (
select 
    t.fname 
    , t.lname 
    , t.dob 
    , t.usermasterid 
    , NewUserMasterId = t2.usermasterid 
    , rn = row_number() over (partition by t.fname, t.lname, t.dob order by t2.usermasterid) 
    from table1 as t 
    inner join table2 as t2 on t.dob = t2.dob 
     and t.fname = t2.fname 
     and t.lname = t2.lname 
     and ltrim(rtrim(t.usermasterid)) = '' 
) 

--/* confirm these are the rows you want updated 
select * 
    from cte as t 
    where t.NewUserMasterId != '' 
    and not exists (
     select 1 
     from cte as i 
     where t.dob = i.dob 
      and t.fname = i.fname 
      and t.lname = i.lname 
      and i.rn>1 
    ); 
--*/ 

/* update those where only 1 usermasterid matches this record 
update t 
    set t.usermasterid = t.NewUserMasterId 
    from cte as t 
    where t.NewUserMasterId != '' 
     and not exists (
     select 1 
     from cte as i 
     where t.dob = i.dob 
      and t.fname = i.fname 
      and t.lname = i.lname 
      and i.rn>1 
    ); 
--*/ 

我使用CTE把解压出来的可读性子查询。根据文档,公用表表达式(cte):

指定临时命名结果集,称为公用表表达式(CTE)。这是从一个简单的查询派生的,并在单个SELECT,INSERT,UPDATE或DELETE语句的执行范围内定义。

row_number()使用分配一个号码对于每一行,从1开始的每个分区的t.fname, t.lname, t.dob。有了这些编号使我们能够检查是否与not exists()条款副本的存在与... and i.rn>1

+0

你能解释WITH CTE的工作原理吗?目的是什么分区? –

+0

@espresso_coffee CTE是一个通用表格表达式。你需要阅读这个主题。该分区与一个分组相似。因此,对于分区 – scsimon

0

你可以使用一个CTE加入之前过滤掉从表1的重复:

这将工作只要在表1中没有确切的重复(相同的人口统计学和相同的ID),如果有确切重复,它们也将被排除在联接之外,但是您可以在CTE之前将它们滤除以避免这种情况。

+0

当你提到'提供他们的'你的意思是我上面张贴的例子吗?也做CTE我们基本上消除了一个表中的所有重复项,这是否正确? –

+0

您在我写这篇文章时没有发布示例。我的意思是,如果你有多行同名,出生日期,*和*代码的行,它也会认为是重复的,不会用于更新。 – APH

+0

CTE计算表中具有相同名称和出生日期的行数,并在更新第二个表之前丢弃重复项。 – APH

0

请尝试以下SQL:

UPDATE Table1 AS tbl1 
INNER JOIN Table2 AS tbl2 
    ON tbl1.dob = tbl2.dob 
    AND tbl1.fname = tbl2.fname 
    AND tbl1.lname = tbl2.lname 
LEFT JOIN Table2 AS tbl3 
    ON tbl3.dob = tbl2.dob 
    AND tbl3.fname = tbl2.fname 
    AND tbl3.lname = tbl2.lname 
    AND tbl3.usermasterid <> tbl2.usermasterid 
SET tbl1.usermasterid = tbl2.usermasterid 
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = '' 
AND tbl3.usermasterid is null 
+0

中列出的每组物品,行号分配了1,2,3等。请您详细说明您的答案吗?我试图理解为什么INNER JOIN第一,然后为表2的左外部联接?谢谢! –

+0

First INNER JOIN将根据dob,fame和lname的值从tbl1和tbl2中选择匹配记录。左连接(自加入tbl2)将从tbl2中选取所有重复记录。 tbl2中的重复记录是dob,fname和lname具有相同值但usermasterid不同(不包括自我比较)的记录。然后在where条件tbl3.usermasterid被检查为空,这意味着在tbl3中没有重复的记录。所以简而言之,它将更新tbl2中tbl1的所有记录,其中重复记录不会在tbl3(tbl2)中退出。 –