是的,你的问题的第二部分有点棘手。B_C_Table一方面,我们有A_C_Table一个A_ID特定 ID 的子集。
现在,如果我们使用外连接,我们将能够看到 in 中的哪些行与 inB_C_Table不匹配A_C_Table:
SELECT *
FROM B_C_Table bc
LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID
请注意,将inac.A_ID = @A_ID放入ON子句而不是 into很重要WHERE,因为在后一种情况下,我们将过滤掉 的不匹配行@A_ID,这不是我们想要的。
下一步(实现最终查询)是对行进行分组并对行进行B计数。现在,我们将计算总行数和匹配行数。
SELECT
bc.B_ID,
COUNT(*) AS TotalCount,
COUNT(ac.A_ID) AS MatchCount
FROM B_C_Table bc
LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID
GROUP BY bc.B_ID
如您所见,要计算匹配项,我们只需计算ac.A_ID值:如果不匹配,则相应的列将被NULL计算在内,因此不会被计算在内。如果确实某些行B_C_Table与 的子集中的任何行都不匹配A_C_Table,我们将看到和的不同值。TotalCountMatchCount
从逻辑上讲,这将我们引向最后一步:比较这些计数。(因为,很明显,如果我们可以获得值,我们也可以比较它们。)但WHERE当然不能在子句中,因为WHERE. 它HAVING是用于比较分组行的值的子句,也包括聚合值。所以...
SELECT
bc.B_ID,
COUNT(*) AS TotalCount,
COUNT(ac.A_ID) AS MatchCount
FROM B_C_Table bc
LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID
GROUP BY bc.B_ID
HAVING COUNT(*) = COUNT(ac.A_ID)
当然,计数值并不是真正需要的,当您删除它们时,您将能够将上述查询与从以下选择的查询进行B_ID联合A_B_rel:
SELECT B_ID
FROM A_B_rel
WHERE A_ID = @A_ID
UNION
SELECT bc.B_ID
FROM B_C_Table bc
LEFT JOIN A_C_Table ac ON bc.C_Value = ac.C_Value AND ac.A_ID = @A_ID
GROUP BY bc.B_ID
HAVING COUNT(*) = COUNT(ac.A_ID)