Сначала получите комплект 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
вы ответите работали ,, но вы ввели в «N» вместо «ч» после И –
Это была опечатка. (На мой взгляд, An n очень похож на h. (По крайней мере, запрос вернул бы ошибку, а не ошибочные результаты.) – spencer7593
ya, ty для объяснения: D thumbs up! –