SQL多表查询:提取两表中唯一邮箱及对应名称的实现问题
提取两表中唯一邮箱及对应名称的SQL实现
数据表结构
表 main
| client_email | client_name |
|---|---|
| bla@email.com | Peter Pan |
| flux@xyz.com | Paul Smith |
表 registered
| client_email | client_name |
|---|---|
| yop@email.com | James Bond |
| flux@xyz.com | Paul Smith |
需求说明
需要编写SQL查询,提取两表中所有唯一的client_email及对应名称(名称来源不限)。已知:
- 两表客户存在交叉及独有情况:部分
main表客户在registered表中,部分registered表客户不在main表中 main表中同一邮箱可能重复出现,registered表中邮箱唯一
遇到的问题
之前尝试用UNION合并两表,但因为UNION是基于邮箱+名称的组合去重,当同一邮箱对应名称存在细微差异(如连字符、重音)时,会导致邮箱重复出现:
SELECT client_email,client_name FROM `main` UNION SELECT client_email,client_name FROM `registered` ORDER BY client_email ASC;
解决方案
方案一:合并后按邮箱分组取任意名称
先通过UNION ALL合并两表所有数据(不提前去重),再按邮箱分组,用聚合函数获取任意一个对应的名称:
SELECT client_email, ANY_VALUE(client_name) AS client_name FROM ( SELECT client_email, client_name FROM `main` UNION ALL SELECT client_email, client_name FROM `registered` ) AS combined_data GROUP BY client_email ORDER BY client_email ASC;
注:
ANY_VALUE()是MySQL支持的函数,若使用其他数据库可替换为对应函数:
- PostgreSQL:
MAX(client_name)或MIN(client_name)- SQL Server:
FIRST_VALUE(client_name) OVER (PARTITION BY client_email ORDER BY client_email)
方案二:先取唯一邮箱再关联取名称(优先指定表的名称)
先获取所有唯一邮箱,再关联两张表,优先选择registered表的名称(因该表邮箱唯一),没有则取main表的:
SELECT unique_emails.client_email, COALESCE(r.client_name, m.client_name) AS client_name FROM ( SELECT client_email FROM `main` UNION SELECT client_email FROM `registered` ) AS unique_emails LEFT JOIN `registered` r ON unique_emails.client_email = r.client_email LEFT JOIN `main` m ON unique_emails.client_email = m.client_email GROUP BY unique_emails.client_email ORDER BY unique_emails.client_email ASC;
期望查询结果
| client_email | client_name |
|---|---|
| bla@email.com | Peter Pan |
| flux@xyz.com | Paul Smith |
| yop@email.com | James Bond |
内容的提问来源于stack exchange,提问作者user22805937
相关产品推荐
相关产品推荐

