設計で参照整合性が適用されている場合は、テーブルのresidences
に参加する必要はありません。 この目的のために。また、UNIQUE
を想定しています またはPK
(residence_id, amenity_id)
の制約 (それ以外の場合は、別のクエリが必要です!)
最適なクエリは、必要なものによって異なります正確に 。
ウィンドウ関数を使用すると、 単一のクエリレベルでもこれを実行できます:
SELECT count(*) OVER () AS ct
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
LIMIT 1;
このウィンドウ関数は、行を集約せずにすべての行に合計カウントを追加します。 SELECT
の一連のイベントについて考えてみましょう。 クエリ:
したがって、同様のクエリを使用して、すべての適格なID(または行全体)を返し、すべての行にカウントを追加することができます(冗長):
SELECT residence_id, count(*) OVER () AS ct
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3;
ただし、サブクエリを使用することをお勧めします。これは、通常ははるかに安価です :
SELECT count(*) AS ct
FROM (
SELECT 1
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
) sub;
あなたはできた IDの配列を返します( set ではなく) 上記)同時に、ほとんどコストをかけずに:
SELECT array_agg(residence_id ) AS ids, count(*) AS ct
FROM (
SELECT residence_id
FROM listed_amenities
WHERE amenity_id IN (48, 49, 50)
GROUP BY residence_id
HAVING count(*) = 3
) sub;
他にも多くのバリエーションがあり、期待される結果を明確にする必要があります。このように:
SELECT count(*) AS ct
FROM listed_amenities l1
JOIN listed_amenities l2 USING (residence_id)
JOIN listed_amenities l3 USING (residence_id)
WHERE l1.amenity_id = 48
AND l2.amenity_id = 49
AND l2.amenity_id = 50;
基本的にそれは関係分割の場合です。ここに技術の武器を集めました: