首先,获取一组services。
将它加入到来自clients 的行中,用于“特定客户”,这样您就拥有了该客户的一组所有服务。
“诀窍”是使用反连接模式来排除 clients_have_services 表中存在“匹配”的行。
如果您有客户端的唯一标识符(并且您只需要单个客户端的列表),则如下所示:
SELECT s.*
FROM services s
LEFT
JOIN clients_have_services h
ON h.service_id = s.id
AND h.client_id = 42
WHERE h.service_id IS NULL
ORDER BY s.id
外连接返回来自services 的所有行,以及来自clients_have_services 表的任何“匹配”行。 “技巧”是 WHERE 子句中的谓词,它排除找到匹配项的任何行,只留下与特定客户端无关的 services。
如果您为多个客户端执行此操作...您还需要返回与服务交叉连接的客户端(作为客户端和服务的交叉产品),然后排除匹配项。
例如:
SELECT c.id AS client_id
, s.*
FROM clients c
CROSS
JOIN services s
LEFT
JOIN clients_have_services h
ON h.service_id = s.id
AND h.client_id = c.id
WHERE h.service_id IS NULL
ORDER BY c.id, s.id
还有一些其他查询模式会返回等效结果,例如NOT EXISTS
SELECT s.*
FROM services s
WHERE NOT EXISTS
( SELECT 1
FROM clients_have_services h
WHERE c.client_id = 42
AND h.service_id = s.id
)
ORDER BY s.id