はい、問題の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
入れることが重要であることに注意してください。これは、必要なものではありません。ON
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
もちろん、カウント値は実際には必要ありません。それらをドロップすると、上記のクエリを次のクエリから選択して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)