如何解决Postgres-多次连接导致我的查询返回错误的数据
|| 我的数据库中有三个表。他们的模式基本上是:books:
id | book_title
books_tags:
id | book_id | tag_id
books_Votes:
id | book_id | Vote
这个想法是能够搜索书籍并通过给定的标签(在这种情况下为716和101)进行过滤。 total_Votes
用于ORDER BY运算符。
SELECT
books.id AS books_id,sum(book_Votes.Vote) AS total_Votes
FROM
books
JOIN
-- works fine without this join
book_Votes ON books.id = book_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
HAVING
count(books.id) = 2
标签过滤本身就很好用。我可以根据需要向IN子句中添加任意数量的标签ID,它将继续过滤结果以仅显示带有这些标签的图书。完善。
当我将第二个JOIN添加到books_Votes
表中时,会出现问题。此联接不会产生任何错误,只会导致查询返回错误的数据-就像忽略标签ID一样。
第二次加入怎么了?
编辑:
这是表中的转储:
books:
id | book_title
----+-----------------
1 | first
2 | second
3 | third book
4 | fourth book
5 | fifth
6 | sixth book
books_tags:
id | book_id | tag_id
----+---------+--------
1 | 1 | 293
2 | 1 | 32
3 | 1 | 370
4 | 2 | 101
5 | 2 | 357
6 | 3 | 554
7 | 3 | 808
8 | 3 | 716
9 | 3 | 101
10 | 4 | 787
11 | 4 | 808
12 | 4 | 322
13 | 5 | 787
17 | 6 | 716
18 | 6 | 554
19 | 6 | 101
books_Votes:
id | book_id | Vote
----+---------+------
2 | 2 | 1
3 | 3 | 1
4 | 4 | 1
7 | 4 | 1
8 | 2 | 1
11 | 5 | 1
12 | 5 | 1
13 | 1 | 1
这是我在发布第二个联接(到books_Votes)时从我发布的查询中返回的数据:
book_id
---------
6
3
如您所见,返回了正确的书。书籍6和3已标有716和101。
这是我将books_Votes表连接到运行查询时返回的结果:
book_id | total_Votes
---------+-------------
3 | 2
2 | 3
解决方法
逐步构建复杂的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
您的版本无效,因为它返回了错误的图书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并不是因为它同时具有两个标签,而是因为它具有两个投票。
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
, 据我了解,您需要所有带有标签716和101的书籍,并且需要每本书的投票数。
select *,(select count(*) from book_votes as vts where vts.book_id = bks.id) as vote_count
from books as bks
where
id in
(
select book_id
from books_tags as tgs
where tgs.tag_id in (716,101)
group by book_id
having count(*) = 2
)
结果:
id book_title vote_count
----------- --------------- -----------
3 third book 1
6 sixth book 0
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。