PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Postgres - Mehrere Verknüpfungen führen dazu, dass meine Abfrage falsche Daten zurückgibt

Erstellen Sie Schritt für Schritt komplexes SQL.

Dadurch erhalten Sie die Bücher, die beide erforderlichen Tags aufweisen. Sie ist nur so zuverlässig wie Ihre Tabellendefinition. Ihre Tabellendefinition sollte nicht zulassen, dass ein Buch zweimal denselben Tag hat. Sie benötigen eine UNIQUE-Einschränkung für (book_id, tag_id).

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

Sie können das in einem JOIN verwenden.

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

Der Beitritt zur Abstimmungstabelle sollte book_id 6 aus dem Ergebnis streichen. (Keine Stimmen für 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

Jetzt können Sie der Abfrage die Abstimmungsspalte hinzufügen.

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

Schließlich können Sie die Stimmen summieren.

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

Ihre Version funktioniert nicht, weil sie die falschen Buch-ID-Nummern zurückgibt. Die Kombination aus dem JOIN auf books_votes und der WHERE-Klausel macht nicht das, was Sie erwartet haben.

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

Buch 2 ist nicht enthalten, weil es beide Tags hat, sondern weil es zwei Stimmen hat.

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