重複した部分集合を見つける

達人SQL1-10の「一意集合と多重集合」のまとめです。

以下のようなグループの中から、同じ名前のメンバーが含まれたグループを見つけてみます。

id group_name member_name
1 A ヤマモト
2 A サトウ
3 B ヤマモト
4 B スズキ
5 B ヤマモト
6 C スズキ
7 C サトウ
8 D ヤマモト
9 D ヤマモト

ここでは、グループBとグループDにヤマモトさんが複数人含まれています。
このような集合から重複した要素のインデックスを取り出す場合は「重複した要素を排除した場合の要素数と、元の要素数が異なっているか」を検索条件に入れてクエリを組み立てます。
この「重複した要素を排除」というはDISTINCTを利用すれば実現できます。

select
    group_name
from
    Groups
group by
    group_name
having
    count(member_name) <> count(DISTINCT member_name);
group_name
B
D

また、この条件をSELECT句に移すことで「そのインデックスが重複した要素を含んでいるか」を結果に表すことも出来ます。

select
    group_name,
    CASE WHEN COUNT(member_name) <> COUNT(DISTINCT member_name) THEN '重複有り' ELSE '重複なし' END AS result
FROM
    Groups
GROUP BY group_name;
group_name result
A 重複なし
B 重複有り
C 重複なし
D 重複有り

DISTINCTがあるおかげで「重複を削除する」が簡単に実現できるところがいいですね。