IN リストで必要な項目だけを選択するにはどうすればよいでしょうか。例えば
select * from pagetags where TagID in (1,2,4)
ここで、上記の 3 つの ID (1、2、4) がすべて割り当てられているすべてのページが必要です。
方法はありますか?その他のオペレーター?私はすでに試しましたが、運が= Any
あり= All
ません。
IN リストで必要な項目だけを選択するにはどうすればよいでしょうか。例えば
select * from pagetags where TagID in (1,2,4)
ここで、上記の 3 つの ID (1、2、4) がすべて割り当てられているすべてのページが必要です。
方法はありますか?その他のオペレーター?私はすでに試しましたが、運が= Any
あり= All
ません。
このタイプの問題の用語は関係分割です。下は片道。
SELECT PageID
FROM pagetags
WHERE TagID IN ( 1, 2, 4 )
GROUP BY PageID
HAVING Count(DISTINCT TagID) = 3
次のようなことを試すことができます:
SELECT id, Tag FROM (
SELECT id, Tag, COUNT(*) OVER(partition by id) as cnt
FROM pagetags
WHERE Tag in(1,2,4)
GROUP BY id, tag
) a WHERE a.cnt = 3
SELECT distinct(PageID)
FROM pagetags
WHERE TagID IN (1,2,4)
and PageID in
(select distinct(PageID) from pagetags group by PageID having count(TagID)=3)
group by PageID
マーティン・スミスからの選択された回答
SELECT PageID
FROM pagetags
WHERE TagID IN ( 1, 2, 4 )
GROUP BY PageID
HAVING Count(DISTINCT TagID) = 3
は正しいですが、速度が問題になる場合は、これらを試してください。
私は同じことをしている大きなテーブルを持っており、次のようにして10倍優れたパフォーマンスを得ました.
300 万行のテーブルから 272 を返すクエリの 2.0 秒に対して 0.2 秒。
また、5 つのタグと同じ 10x の大きなテーブルでテストしましたが、現在は 0.5 対 5.0 です。
インデックスは PageID、数百万の PageID と数百の TagID を持つ TagID です。
多くのオブジェクトが複数値プロパティにタグ付けされている一般的なシナリオ。
SELECT distinct(p1.PageID)
FROM pagetags p1
JOIN pagetags p2
ON p2.PageID = p1.PageID
AND p2.TagID = 2
JOIN pagetags p3
ON p3.PageID = p1.PageID
AND p3.TagID = 4
WHERE p1.PageID = 1
ORDER BY p1.PageID
また
SELECT distinct(PageID)
FROM pagetags
WHERE TagID = 1
INTERSECT
SELECT distinct(PageID)
FROM pagetags
WHERE TagID = 2
INTERSECT
SELECT distinct(PageID)
FROM pagetags
WHERE TagID = 4
ORDER BY PageID
結合が 5 つを超えると、クエリ オプティマイザーが不適切な決定を下すことが多いため、最後の結合を優先します。
これにより、別の集計に必要な場合でも Group By を使い果たしません。