在联接表

时间:2015-04-24 16:15:10

标签: sql-server group-by self-join

我一直坚持这个问题一段时间,我希望我能在这里得到一些帮助!

在SQL Server 2012中,我有两个表,Name(包含Name和ID)和Address(包含ID和AddressID),​​我需要根据类似的声音名称和相同的AddressID来查找重复记录。

这是我目前的代码:

SELECT DISTINCT a.ID, a.Name, c.ID, c.Name
FROM Name a 
JOIN Address b 
    ON a.ID = b.ID
JOIN Name c 
    ON SOUNDEX(a.Name) = SOUNDEX(c.Name) 
    AND a.ID < c.ID
JOIN Address d
    ON c.ID = d.ID  
WHERE a.Name = c.Name 

我返回一个包含重复信息的表:每对都是不同的,但我不需要知道所有可能的对,我只想要一个类似名称和ID的列表。

我一直在尝试实现GROUP BY和HAVING子句,但我似乎无法得到我想要的结果。

任何想法都会非常感激!

编辑:

My current list looks like this:
ID1     Name1       ID2    Name2       AddressID
1       Smith       10     Smythe      8
1       Smith       11     Smithy      8
1       Smith       12     Smythe      8
1       Smith       13     Smithy      8
10      Smith       12     Smythe      8
10      Smith       11     Smithy      8
10      Smith       13     Smythy      8
11      Smith       12     Smithe      8
11      Smith       13     Smythy      8
12      Smith       13     Smythy      8
2       John        14     Jon         9
2       John        15     Jonn        9
...

我希望它返回这样的内容:

ID1     Name1       ID2    Name2       AddressID
1       Smith       10     Smythe      8
1       Smith       11     Smithy      8
1       Smith       12     Smythe      8
1       Smith       13     Smithy      8
2       John        14     Jon         9
2       John        15     Jonn        9
...

我设法通过将我的表转储到临时表中来创建一个相当不优雅的解决方案,然后循环遍历行并将其插入到最终表中,如果该表中尚不存在ID号。在我看来,应该有更好的方法来做到这一点!

3 个答案:

答案 0 :(得分:1)

这是两个单独的结果集,具有匹配的地址和相似的名称。你需要一个联盟来获得结果

Select Distinct C.ID, C.Name, D.ID, D.Name From Address A Inner Join Address B On A.AddressID = B.AddressID Inner Join Name C On A.ID = C.ID Inner Join Name D On B.ID = D.ID Union Select A.ID, A.Name, B.ID, B.Name From Name A Join Name B On SOUNDEX(A.Name) = SOUNDEX(B.Name)

我的评论仍然有效。如果有多个匹配项,您希望输出结果如何。

请原谅任何语法错误,因为我无法尝试运行此错误。

答案 1 :(得分:0)

我认为应该这样做。 DIFFERENCE比较SOUNDEX的结果并将它们从0到4评级,其中4是最相似的。您可能需要调整我的标准,以便或多或少地允许。

DECLARE @Name TABLE (NameID int, Name varchar(50));
DECLARE @Address TABLE (AddressID int, NameID int);

INSERT @Name VALUES (1, 'Smith');
INSERT @Name VALUES (2, 'Smyth');
INSERT @Name VALUES (3, 'Smythe');
INSERT @Name VALUES (4, 'Jones');
INSERT @Name VALUES (5, 'Jonas');
INSERT @Name VALUES (6, 'Johnson');

INSERT @Address VALUES (1, 1);
INSERT @Address VALUES (2, 2);
INSERT @Address VALUES (1, 3);
INSERT @Address VALUES (4, 4);
INSERT @Address VALUES (4, 5);
INSERT @Address VALUES (5, 5);
INSERT @Address VALUES (6, 6);
INSERT @Address VALUES (1, 6);

SELECT  *
FROM    @Name N1
JOIN    @Name N2    ON DIFFERENCE(N1.Name, N2.Name) >= 3 AND N1.NameID < N2.NameID
JOIN    @Address A1 ON A1.NameID = N1.NameID
JOIN    @Address A2 ON A2.NameID = N2.NameID
WHERE   A1.AddressID = A2.AddressID

答案 2 :(得分:0)

尝试这样的事情(你可能想在第一部分添加额外的重复数据删除规则):

Select *
, RowNumber() over (partition by Sound order by NamePopularity desc, ID) as RowN
into #temp1
from (
   Select ID, Name, SoundEx(Name) as Sound
   , count(ID) over (partition by Name) as NamePopularity
   from Name
) a

Select a.ID, a.Name, b.ID, b.Name from #temp1 a
inner join Name b
on soundex(a.Name) = soundex(b.Name) and a.name <> b.name
where a.RowN = 1

将为每个声音组选择最常用的名称,然后将声音组中的所有其他名称加入其中。删除声音组中单独的名称。