如何在大桌子上执行自我联接

时间:2019-06-24 04:34:01

标签: sql sql-server tsql

我有一个很大的表(约7000万行),其中id列是从另一个表派生的。 ID分配错误。 2个名字不同的人被分配了相同的ID,而他们不应该被分配。从理论上讲,我理解在ID相同且第一个不相等的同一张表上进行自我联接应该起作用,但由于行数巨大,查询将卡住。关于如何进行的任何想法?

我试图过滤掉一些数据,然后将内容复制到一个全新的表中,但无济于事。

我的代码看起来像这样

select distinct m1.first_name, m.first_name, m1.id from member m inner join member_1 m1 on m.id = m1.id and m.first_name <> m1.first_name

数据看起来像这样

run_id  first_name      id 
1       aaaa            1 
2       aaaa            1 
3       aaaa            1 
3       bbbb            2 
3       cccc            3 
4       aaaa            1 
4       bbbb            4 
5       bbbb            4 
5       cccc            3 
6       aaaa            1 
6       bbbb            4 
6       cccc            3 

在这种情况下,如果您注意到,在run_id 2中,bbbb被分配了ID 2,在运行5和6中,bbbb被分配了id4。在这种情况下,bbbb似乎被分配了2个id。我如何仅过滤掉此类行,而不提取aaaa和cccc。使用distinct正在耗尽我的资源,这似乎不是一个好选择

2 个答案:

答案 0 :(得分:2)

group byhavingcount distinct一起使用,而不是自我联接:

SELECT first_name
FROM member 
GROUP BY first_name
HAVING COUNT(DISTINCT Id) > 1

此查询将返回包含多个first_name的{​​{1}}的唯一列表。

如果索引运行仍然太慢,可以在idfirst_name上添加索引来提高性能。

答案 1 :(得分:1)

我建议使用exists

select m.*
from member_1 m
where exists (select 1
              from member_1 m2
              where m2.id = m.id and m2.first_name <> m.first_name
             );

然后,为了提高性能,您需要在member_1(id, first_name)上建立索引。

如果只需要ID,则可以使用聚合:

select id
from member_1
group by id
having min(first_name) <> max(first_name);