Client
表:
Status
表:
客户端表已连接到 [CID] 上的状态表。我想要未将任何状态设置为“不活动”的客户的 [CID]。
这是我的尝试:
SELECT
A.[CID], B.[Status]
FROM
[Client table] AS A
INNER JOIN
[Status table] B ON A.[CID] = B.[CID]
WHERE
B.[Status] = 'Not Active'
在这种情况下,它应该显示具有 CID 2 和 3 的客户端,而不显示具有 CID 1 的客户端。但是,当输入“状态 = 不活动”条件时,我得到了所有 CID 1、2 和 3。通过上述查询,我获得了所有三个 CID。
如何改进查询以仅显示 CID 2 和 3?我在这里做错了什么?
最佳答案
NOT EXISTS
是执行此操作的最有效方法。
不幸的是,SQL Server 要求子查询中至少有一列,因此您可以只执行 SELECT 1
或 SELECT NULL
。无论您做什么都会被忽略,它只是在子查询中查找行是否存在。请注意内部 WHERE
中与外部查询的相关性。
SELECT
c.CID
FROM Client c
WHERE NOT EXISTS (SELECT 1
FROM Status s
WHERE s.CID = c.CID -- correlation
AND s.Status = 'Not Active'
);
如果您确实想使用联接查看所有 Status
行,那么窗口函数可能是最佳选择。
这里我们使用一个窗口函数,它可以一次计算多行,同时仍然返回所有行而不是聚合。 PARTITION BY 的工作方式与这里的 GROUP BY 类似,而 CASE WHEN 使其成为条件,因此它只计算与条件匹配的行。
SELECT
c.CID
FROM Client c
JOIN (
SELECT s.*,
countNotActive = COUNT(CASE WHEN s.Status = 'Not Active' THEN 1 END) OVER (PARTITION BY s.CID)
FROM Status s
) s ON s.CID = c.CID
WHERE s.countNotActive = 0;
关于sql - 过滤具有一对多关系的两个表之间的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76274963/