10

tagidcontentidの 2 つの列を持つ「タグ」テーブルがあるとします。各行は、コンテンツに割り当てられたタグを表します。tagid 334、338、および 342 でタグ付けされたすべてのコンテンツの contentid を取得するクエリが必要です。

これを行う「簡単な」方法は次のとおりです(疑似コード):

select contentid from tags where tagid = 334 and contentid in (
    select contentid from tags where tagid = 338 and contentid in (
        select contentid from tags where tagid = 342
    )
)

しかし、私の直感では、これを行うには、より優れた、より高速で拡張可能な方法があることがわかります。たとえば、12 個のタグの交点を見つける必要がある場合はどうすればよいでしょうか? これはすぐに恐ろしくなります。何か案は?

編集: これは、この優れたブログ投稿でも取り上げられていることが判明しました。

4

5 に答える 5

24
SELECT contentID
FROM tags
WHERE tagID in (334, 338, 342)
GROUP BY contentID
HAVING COUNT(DISTINCT tagID) = 3


--In general
SELECT contentID
FROM tags
WHERE tagID in (...) --taglist
GROUP BY contentID
HAVING COUNT(DISTINCT tagID) = ... --tagcount
于 2008-10-02T18:41:17.440 に答える
2

これは、オブジェクトとタグの非常に大きなデータベースで、私にとってよりもはるかに高速に機能するソリューションです。これは、3 つのタグが交差する例です。object-tag テーブル ( ) で多くの結合を連鎖させて同じオブジェクトを示し、節objtagsでタグ ID を規定するだけです。WHERE

SELECT w0.objid

FROM       objtags t0
INNER JOIN objtags t1 ON t1.objid=t0.objid
INNER JOIN objtags t2 ON t2.objid=t1.objid

WHERE t0.tagid=512
  AND t1.tagid=256
  AND t2.tagid=128

なぜこれが速く走るのか分かりません。MusicBrainz サーバーの検索コードに触発されました。Postgres でこれを行うと、通常、HAVING COUNT(...)ソリューションよりも 8 ~ 10 倍高速化されます。

于 2008-11-20T04:17:36.273 に答える
1

私が考えることができる唯一の代替方法は次のとおりです。

select a.contentid from tags a
inner join tags b on a.contentid = b.contentid and b.tagid=334
inner join tags c on a.contentid = c.contentid and c.tagid=342
where a.tagid=338
于 2008-10-02T18:40:35.103 に答える
0

これが良いかどうかはわかりませんが、より保守しやすいかもしれません

select contentid from tags where tagid = 334
intersect
select contentid from tags where tagid = 338
intersect
select contentid from tags where tagid = 342

動的に構築する必要がありますが、元のソリューションほど悪くはありません。

于 2008-10-02T18:45:02.033 に答える
-1

SQLの種類は?MS SQL Server、Oracle、MySQL?

SQL Server では、これは以下と同等ではありません。

select contentid from tags where tagid IN (334,338,342)
于 2008-10-02T18:42:02.043 に答える