我有两个表:
db_contacts
Phone | Name | Last_Name
--------------------
111 | Foo | Foo
222 | Bar | Bar
333 | John | Smith
444 | Tomy | Smith
users_contacts
User_ID | Phone
--------------------
1 | 123
1 | 111
2 | 222
2 | 333
3 | 111
3 | 333
4 | 444
上面的通知:
我需要通过MySQL查询获得这些结果。
换句话说:在db_contacts中存在该电话号码的情况下,如何选择所有具有唯一电话号码的用户。
我需要我的最终结果是这样的:
User_ID | Phone | Name | Last_Name
------------------------------------
2 | 222 | Bar | Bar
4 | 444 | Tomy | Smith
PS:“电话”列之间没有外键,因为用户可以拥有不在db_contacts中的电话。
在现实生活中,db_contacts包含大约一百万条记录,而user_contacts包含约五百万条记录。
我尝试和失败的事情,并且花费大量时间执行:
SELECT *
FROM users_contacts
WHERE users_contacts.phone IN (
SELECT users_contacts.phone
FROM `users_contacts`
JOIN db_contacts ON db_contacts.phone = users_contacts.phone
GROUP BY users_contacts.phone
HAVING COUNT(users_contacts.phone) = 1
)
谢谢您的答复,我提供了适合我情况的解决方案。
答案 0 :(得分:1)
我想你想要
select uc.*
from user_contacts uc
where not exists (select 1
from user_contacts uc2
where uc2.phone = uc.phone and uc2.user_id <> uc.user_id
);
为了提高性能,您希望在user_contacts(phone, user_id)
上建立索引。
另一种方法是:
select max(user_id) as user_id, phone
from user_contacts
group by phone
having count(*) = 1;
not exists
版本可能会更快。
答案 1 :(得分:1)
我将使用带有JOIN
条件的简单NOT EXISTS
。这通常是检查某项内容是否重复的最有效方法;与您的解决方案相比,这具有避免聚合的优势。
SELECT uc.User_ID, dc.*
FROM users_contacts uc
INNER JOIN db_contacts dc ON uc.Phone = dc.Phone
WHERE NOT EXISTS (
SELECT 1
FROM users_contacts uc1
WHERE uc1.Phone = dc.Phone AND uc1.User_ID != uc2.User_ID
)
提示:请考虑设置以下索引:
users_contacts(Phone, User_ID)
db_contacts(Phone)
答案 2 :(得分:1)
首先,我要感谢发布解决方案的所有人,他们都工作了。
但是我对响应时间有些挑剔,其他人提供的解决方案花了很多时间才能执行,几秒钟。
万一有人遇到类似问题,我最后创建了一个新表,称为users_unique_contacts,并在users_contacts上创建了一个触发器AFTER INSERT,以检查新创建的联系人是否在users_unique_contacts中存在(如果不存在) ,添加它,否则将其删除,因为它意味着该号码不再是唯一的。
我的触发器像这样:
BEGIN
IF EXISTS (SELECT 1 = 1 FROM users_unique_contacts WHERE phone = new.phone LIMIT 1) THEN
BEGIN
DELETE FROM users_unique_contacts WHERE phone = new.phone LIMIT 1;
END;
ELSE
BEGIN
INSERT INTO users_unique_contacts (user_id,phone) VALUES (new.user_id, new.phone);
END;
END IF;
END
现在,每次我想要一个用户的唯一编号时,我都会查询users_unique_contacts,执行时间为毫秒。