PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Postgres - Множеството присъединявания карат моята заявка да връща неправилни данни

Изградете сложен SQL стъпка по стъпка.

Това ви дава книгите, които имат и двата задължителни етикета. Толкова е надеждно, колкото и дефиницията на вашата таблица. Вашата дефиниция на таблица не трябва да позволява една книга да има един и същ етикет два пъти. Имате нужда от УНИКАЛНО ограничение за (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

Можете да го използвате в 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_id 6 от резултата. (Няма гласове за 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

Вашата версия не работи, защото връща грешни идентификационни номера на книги. Комбинацията от JOIN на books_votes и клаузата 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 е включена не защото има и двата етикета, а защото има два гласа.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да инсталирам postgres с NSIS с всички параметри?

  2. PostgreSQL:Създаване на индекс за булева колона

  3. SQL 'AT TIME ZONE', заявка широка и с 'SELECT' всички колони (име на таблица.*) израз

  4. Създаване на PostgreSQL последователност към поле (което не е ID на записа)

  5. Функция за проследяване на зависимости