是的,你的问题的第二部分有点棘手。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
,我们将看到和的不同值。TotalCount
MatchCount
从逻辑上讲,这将我们引向最后一步:比较这些计数。(因为,很明显,如果我们可以获得值,我们也可以比较它们。)但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)