我有两个服务提供商表,providers
和providers_clean
。 providers
包含数千个格式很差的数据提供商,providers_clean
只有一些提供商仍然存在于'脏'表中。
我希望系统使用此数据在用户“清理”数据时保持正常运行,因此我希望能够选择已经“清理”的所有行以及仍然'脏',同时排除任何与'干净'相同的'脏'结果。
如何从providers_clean
表中选择与providers
表中所有提供商合并的所有提供商,并排除那些已经“清理”的提供商
我试过了:
SELECT * FROM providers WHERE NOT EXISTS (SELECT * FROM providers_clean WHERE providers_clean.id = providers.id)
它给了我providers
排除'干净'的所有'脏'结果,但是如何重写查询现在合并来自providers_clean
的所有'干净'?
这是我正在尝试做的直观表达:
Clean Table
+----+-------------------+
| ID | Name |
+----+-------------------+
| 1 | Clean Provider 1 |
| 4 | Clean Provider 4 |
| 5 | Clean Provider 5 |
+----+-------------------+
Dirty Table
+----+------------------+
| ID | Name |
+----+------------------+
| 1 | Dirty Provider 1 |
| 2 | Dirty Provider 2 |
| 3 | Dirty Provider 3 |
| 4 | Dirty Provider 4 |
| 5 | Dirty Provider 5 |
+----+------------------+
Desired Result
+----+------------------+
| ID | Name |
+----+------------------+
| 1 | Clean Provider 1 |
| 2 | Dirty Provider 2 |
| 3 | Dirty Provider 3 |
| 4 | Clean Provider 4 |
| 5 | Clean Provider 5 |
+----+------------------+
由于
更新
这是有效的,但是,有更有效的方法来编写此查询吗?
SELECT providers.id AS id,
CASE
WHEN
providers_clean.id IS NOT NULL
THEN
providers_clean.provider_name
ELSE
providers.provider_name
END AS pname,
CASE
WHEN
providers_clean.id IS NOT NULL
THEN
providers_clean.phone
ELSE
providers.phone
END AS pphone,
CASE
WHEN
providers_clean.id IS NOT NULL
THEN
providers_clean.website
ELSE
providers.website
END AS pwebsite
FROM providers
LEFT JOIN providers_clean ON providers_clean.id = providers.id
ORDER BY providers.id asc
答案 0 :(得分:1)
好像你需要LEFT JOIN
:
SELECT COALESCE(pc.ID, p.ID), COALESCE(pc.Name, p.Name)
FROM providers AS p
LEFT JOIN providers_clean AS pc ON p.ID = pc.ID
这个查询本质上是做什么的:如果记录存在于' clean'然后选择这一个,否则从'脏'中选择一个。表
答案 1 :(得分:1)
我 爱 ,经常参考this 以及this关于JOIN如何工作的直观解释。
根据它们,你需要一个FULL OUTER JOIN,不包括两个表中的项目("外部不包括JOIN和#34;):
SELECT *
FROM providers p
FULL OUTER JOIN providers_clean pc
ON pc.id = p.id
WHERE p.id IS NULL OR pc.id IS NULL;
更新不幸的是,MySQL中没有FULL OUTER JOIN,所以你必须模仿它。我使用this回答来做到这一点:
select p.*
from providers p left join providers_clean pc on pc.id = p.id
where pc.id is null
union all
select pc.*
from providers p right join providers_clean pc on pc.id = p.id;
第一个SELECT是脏的,没有干净的副本,第二个SELECT只是干净的。
答案 2 :(得分:1)
你需要做一个从Dirty到Clean的外连接(因为Dirty所有行都是Clean,但反之亦然)
SELECT dirty.id AS id,
CASE
WHEN clean.id IS NOT NULL THEN clean.name
ELSE dirty.name
END AS new_name
FROM dirty
LEFT JOIN clean ON clean.id = dirty.id
ORDER BY dirty.id asc