はい、問題の2番目の部分は少し注意が必要です。B_C_Table一方では、特定のIDがどこにあるかのサブセットがA_C_Tableあります。A_ID
B_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
後者の場合、一致しない行を除外するため、をではなく句にac.A_ID = @A_ID入れることが重要であることに注意してください。これは、必要なものではありません。ONWHERE@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もちろん、カウント値は実際には必要ありません。それらをドロップすると、上記のクエリを次のクエリから選択してUNIONすることができます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)