使用 NOT IN / NOT EXISTS(?) 和三个表的 SQL 查询的结构

Structure of SQL query using NOT IN / NOT EXISTS(?) with three tables

我需要帮助找出查询的正确结构

find the names of those clients, who stopped in exactly the same hotels as John Doe.

我有桌子:

Clients(clientID, clientName)

ClientTour(clientID, tourID)

Tours(tourID, country, hotel)

全部写成一个查询。

我对 SQL 很陌生,不能为它写下正确的子查询,因为它使用三个表...我有点了解如何为两个表编写类似的查询,但是当我试着写这个……好吧,我迷路了。 =/

据我所知,我必须找到那些客户的名字, 谁停在

[John Doe 停靠的所有酒店] - [只有 John Doe 停靠的酒店]

但谁从未停止过那些

[李四从未下榻的酒店]。

逻辑上对吗?如果是,那么我得到的部分是

SELECT c1.clientName

FROM Clients c1

WHERE c1.clientID NOT IN (clientIDs of clients in [Hotels where John Doe never stopped])

AND c1.clientID IN (clientIDs of clients in [[All Hotels where John Doe stopped] - [Hotels where only John Doe stopped]])

但无法弄清楚以斜体标记的部分...我如何找到曾在 John Doe did/didn 未下榻的酒店或仅 John Doe 下榻的酒店下榻的客户?

另外,有没有更简单的方法来写下这个查询?

编辑:
1. 在外层SELECT增加了一个GROUP BY子句,取代了DISTINCT的需要,并在结果中为每个客户增加了countnig家酒店的选项设置。请注意,结果集仅包含 'John Doe' 入住过的酒店。
2. 添加了一个 SELECT 语句来计算 'John Doe' 访问过的酒店数量。
3. 添加了一个 HAVING 子句以从结果集中删除酒店数量不同于 'John Doe'.

的客户
SELECT C.clientName 
FROM (Clients AS C INNER JOIN ClientTour AS CT ON C.clientID = CT.clientID) INNER JOIN Tours AS T ON CT.tourID = T.tourID
WHERE C.clientName <> 'John Doe' 
    AND T.hotel IN 
(
    SELECT DISTINCT T1.hotel
    FROM (Clients AS C1 INNER JOIN ClientTour AS CT1 ON C1.clientID = CT1.clientID) INNER JOIN Tours AS T1 ON CT1.tourID = T1.tourID
    WHERE C1.clientName = 'John Doe' 
)
GROUP BY C.clientName 
HAVING COUNT(DISTINKT T.hotel) = SELECT COUNT(DISTINCT T2.hotel)
    FROM (Clients AS C2 INNER JOIN ClientTour AS CT2 ON C2.clientID = CT2.clientID) INNER JOIN Tours AS T2 ON CT2.tourID = T2.tourID
    WHERE C2.clientName = 'John Doe' 

第一次尝试:

SELECT C.clientName 
FROM (Clients AS C INNER JOIN ClientTour AS CT ON C.clientID = CT.clientID) INNER JOIN Tours AS T ON CT.tourID = T.tourID
WHERE Trim(C.clientName) <> 'John Doe' 
    AND T.hotel IN 
(
    SELECT DISTINCT T1.hotel
    FROM (Clients AS C1 INNER JOIN ClientTour AS CT1 ON C1.clientID = CT1.clientID) INNER JOIN Tours AS T1 ON CT1.tourID = T1.tourID
    WHERE Trim(C1.clientName) = 'John Doe' 
)