0

通常のpost、tag、およびtag_postテーブルを含むpost/tagデータベースがあります。tag_postテーブルには、tagidフィールドとpostidフィールドが含まれています。

投稿をクエリする必要があります。特定のタグを持つ投稿を取得する場合は、結合を使用する必要があります。

... INNER JOIN tag_post ON post.id = tag_post.postid 
WHERE tag_post.tagid = {required_tagid}`

tagIdAとtagIdBを持つ投稿をフェッチする場合は、2つの結合を使用する必要があります(最終的にはこれに同意しました)。

次に、特定のタグがない投稿をクエリする必要があります。あまり考えずに、私はに変更し=ました!=

... INNER JOIN tag_post ON post.id = tag_post.postid 
WHERE tag_post.tagid != {certain_tagid}`

ブーム!間違った論理!

私はこれを思いついた-ここにロジックを書くだけだ:

... INNER JOIN tag_post ON post.id = tag_post.postid 
WHERE tag_post.postid NOT IN 
(SELECT postid from tag_post where tagid = {certain_tagid})

私はこれがうまくいくことを知っていますが、私が育った方法のために、私がサブクエリでクエリを書くときはいつでも罪悪感を感じます(正当化されるかどうか)。

これを行うためのより良い方法を提案しますか?

4

3 に答える 3

2

「(特定のタグの)タグに一致しない投稿のすべての行を検索する」と考えることができます。

これは、LEFTJOINの教科書のユースケースです。

LEFT JOIN tag_post ON post.id = tag_post.postid AND tag_post.tagid = {required_tagid}
WHERE tag_post.tag_id IS NULL

結合のON句にタグIDが必要であることに注意してください。

結合タイプのリファレンスについては、ここを参照してください:http: //www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

于 2012-09-15T18:09:42.697 に答える
1

Gavin Towey の良い答えに加えて、not existsサブクエリを使用できます。

where   not exists
        (
        select  *
        from    tag_post
        where   post.id = tag_post.postid
                and tag_post.tagid = {required_tagid}
        )

データベースは通常、両方のバリアントを同じ方法で実行します。私は個人的にnot existsアプローチが読みやすいと感じています。

于 2012-09-15T18:16:38.983 に答える
1
  1. tagIdA と tagIdB を持つ投稿を取得したい場合は、2 つの結合を使用する必要があります (最終的にはこれに同意しました)。

    他の方法があります。

    id123 と 456の両方でタグ付けされたすべての投稿をすべて取得するには、これらのタグのみをtagidフィルタリングtag_postしてグループ化し、投稿ごとにグループ化し、予想よりも少ないタグを含むグループを削除します。posts次に、結果を使用してテーブルをフィルタリングできます。

    SELECT * FROM posts WHERE id IN (
      SELECT   postid
      FROM     tag_post
      WHERE    tagid IN (123,456)
      GROUP BY postid
      HAVING   COUNT(*) = 2
    )
    

    投稿に同じタグを複数回付けることができる場合は、パフォーマンスの低いタグtagidに置き換える必要があります。COUNT(*)COUNT(DISTINCT tagid)

  2. ここで、特定のタグを持たない投稿をクエリする必要があります。

    これは、アンチ結合として知られています。あなたが提案したように、最も簡単な方法はIN、上記のクエリを に置き換えることです。NOT IN私はそれについてあまり罪悪感を感じません。別の方法は、 @GavinTowey の回答で提案されているように、外部結合を使用することです。

于 2012-09-15T18:16:59.677 に答える