问题描述
假设我们有两个表:
-
clientOffices
,其中包含每个客户拥有的办公室列表。 -
clusters
是城市群
clientOffices
-----------------------------
clientId | office
-----------------------------
1 London
1 Manchester
1 Edinburgh
1 Bonn
2 London
2 Frankfurt
2 Bonn
3 Manchester
3 Frankfurt
-----------------------------
clusters
-----------------------------
clusterName | city
-----------------------------
X London
X Manchester
Y Manchester
Y Frankfurt
Y Bonn
Z London
Z Bonn
-----------------------------
现在,我们需要一个查询来告诉我们: 对于每个客户,它们完全位于哪些群集中? 也就是说,他们在集群中每个城市都有办公室?
Desired result:
-------------------------------------------
clientOffices.clientId | clusters.clusterName
-------------------------------------------
1 X
1 Z
2 Z
3 Null
--------------------------------------------
我是MysqL Noob-尝试了不同类型的联接,但无法获得此结果。如果可以的话,那就太好了。
提琴:https://www.db-fiddle.com/f/2GTBVXm9StNHcyuSqSZikW/0
解决方法
这将显示所有具有完整集群的客户端名称
SELECT DISTINCT a.clientName,a.clusterName
FROM
(
SELECT clientOffices.clientName,clusters.clusterName,COUNT(*) AS counts
FROM clientOffices
LEFT JOIN clusters ON clusters.city = clientOffices.office
GROUP BY clientOffices.clientName,clusters.clusterName
) AS a
JOIN
(
SELECT clusterName,COUNT(*) AS counts
FROM clusters
GROUP BY clusterName
) AS b
ON a.clusterName = b.clusterName AND a.counts = b.counts
UNION
SELECT c.clientName,null AS clusterName FROM
(
SELECT a.clientName,COUNT(*) as invalid_office
FROM
(
SELECT clientOffices.clientName,COUNT(*) AS counts
FROM clusters
GROUP BY clusterName
) AS b
ON a.clusterName = b.clusterName AND a.counts != b.counts
GROUP BY a.clientName
) AS c
JOIN
(
SELECT clientName,COUNT(*) AS office_count
FROM clientOffices
GROUP BY clientName
) AS d
ON c.clientName = d.clientName AND c.invalid_office = d.office_count;
https://www.db-fiddle.com/f/6jKvKXPYvsLeXgm3Qv1nHu/10
,这看起来像是关系划分问题。我将其写为聚合查询,并在having
子句中进行过滤:
select co.clientid,cl.clusterName
from clientoffices co
inner join clusters cl on cl.city = co.office
group by co.clientid,cl.clusterName
having count(*) = (select count(*) from clusters cl1 where cl1.clusterName = cl.clusterName)
对于示例数据this produces:
| clientid | clusterName |
| -------- | ----------- |
| 1 | X |
| 1 | Z |
| 2 | Z |