sql >> データベース >  >> RDS >> PostgreSQL

Postgres-複数の結合により、クエリが誤ったデータを返す原因になっています

    複雑なSQLを段階的に構築します。

    これにより、両方の必要なタグが付いた本が得られます。それはあなたのテーブル定義と同じくらい信頼できるだけです。テーブル定義では、1冊の本に同じタグを2回含めることはできません。 (book_id、tag_id)にUNIQUE制約が必要です。

    SELECT book_id 
    FROM books_tags
    WHERE books_tags.tag_id IN (716, 101)
    GROUP BY book_id
    HAVING COUNT(tag_id) = 2
    
    book_id
    --
    6
    3
    

    JOINで使用できます。

    SELECT books.id
    FROM books
    INNER JOIN (
        SELECT book_id 
        FROM books_tags
        WHERE books_tags.tag_id IN (716, 101)
        GROUP BY book_id
        HAVING COUNT(tag_id) = 2) bt ON bt.book_id = books.id
    
    book_id
    --
    6
    3
    

    投票表に参加すると、book_id6が結果から削除されます。 (6票はありません。)

    SELECT books.id
    FROM books
    INNER JOIN (
        SELECT book_id 
        FROM books_tags
        WHERE books_tags.tag_id IN (716, 101)
        GROUP BY book_id
        HAVING COUNT(tag_id) = 2) bt ON bt.book_id = books.id
    INNER JOIN books_votes bv ON bv.book_id = books.id
    
    book_id
    --
    3
    

    これで、投票列をクエリに追加できます。

    SELECT books.id, bv.vote
    FROM books
    INNER JOIN (
        SELECT book_id 
            FROM books_tags
        WHERE books_tags.tag_id IN (716, 101)
        GROUP BY book_id
        HAVING COUNT(tag_id) = 2) bt ON bt.book_id = books.id
    INNER JOIN books_votes bv ON bv.book_id = books.id
    
    book_id  vote
    --
    3        1
    

    最後に、投票を合計することができます。

    SELECT books.id, SUM(bv.vote) AS total_votes
    FROM books
    INNER JOIN (
        SELECT book_id 
            FROM books_tags
        WHERE books_tags.tag_id IN (716, 101)
        GROUP BY book_id
        HAVING COUNT(tag_id) = 2) bt ON bt.book_id = books.id
    INNER JOIN books_votes bv ON bv.book_id = books.id
    GROUP BY books.id;
    
    book_id  total_votes
    --
    3        1
    

    間違ったブックID番号が返されるため、お使いのバージョンは機能しません。 books_votesのJOINとWHERE句の組み合わせは、期待どおりに機能しません。

    SELECT books.id AS books_id
    FROM books
    JOIN books_votes ON books.id = books_votes.book_id
    JOIN books_tags ON books.id = books_tags.book_id
    WHERE books_tags.tag_id IN (716, 101)
    GROUP BY books.id 
    
    books_id
    --
    3
    2
    

    ブック2は、両方のタグがあるためではなく、2票があるために含まれています。

    SELECT books.id AS books_id, books_tags.tag_id, books_votes.vote
    FROM books
    JOIN books_votes ON books.id = books_votes.book_id
    JOIN books_tags ON books.id = books_tags.book_id
    WHERE books_tags.tag_id IN (716, 101)
    ORDER BY books_id, tag_id
    
    book_id  tag_id     vote
    --
    2        101        1
    2        101        1
    3        101        1
    3        716        1
    


    1. 複数の行を1つの行に組み合わせる方法、オラクル

    2. Postgres-列とそのデータを暗号化する方法

    3. Oracle正規表現の最後の出現からの文字列の分割

    4. NULLの可能性があるパラメーターを持つSQL関数