【问题标题】:Postgres query returning books with only one authorPostgres 查询返回只有一位作者的书籍
【发布时间】:2019-10-11 21:41:27
【问题描述】:

我正在尝试从书籍中返回书名、书籍摘要和作者姓名进行查询,其中只有一位作者按书籍 ID 排序。一本书可以有很多作者,一个作者可以写很多书,所以这是多对多的关系,但我做错了什么或忘记了什么。

我的桌子是:

book_tb(id, title, summary);
author_tb(id, name);
book_author_tb(id, book_id, author_id);

我已经试过了:

SELECT b.title, b.summary, a.name 
FROM book_tb b
INNER JOIN book_author_tb ba ON b.id = ba.book_id
INNER JOIN author_tb a ON ba.author_id = a.id
GROUP BY b.title, b.summary, a.name, b.id
HAVING count(ba.author_id) = 1
ORDER BY b.id;

【问题讨论】:

  • 能否请您发布数据样本以及输出的样子?
  • 是的,a.nameGROUP BY 列表中,您会为每个作者获得一个组,其中HAVING count(ba.author_id) = 1 始终为真。
  • 一位作者是什么意思?是只有一位作者的书,还是您想选择所有书籍,如果一本书的作者不止一位,则应随机选择一位?

标签: sql postgresql


【解决方案1】:

这样做的一种方法是:

SELECT b.title, b.summary, a.name 
FROM book_author_tb ba 
INNER JOIN book_tb b ON b.id = ba.book_id
INNER JOIN author_tb a ON a.id = ba.author_id
WHERE (
  SELECT COUNT(*) 
  FROM book_author_tb
  WHERE book_id = b.id
) = 1
ORDER BY b.id

这个:

SELECT COUNT(*) FROM book_author_tb WHERE book_id = b.id

确保退回的图书只有一位作者。
另一种方式(也许更有效):

SELECT b.title, b.summary, a.name 
FROM (
  SELECT book_id, MAX(author_id) author_id 
  FROM book_author_tb
  GROUP BY book_id
  HAVING COUNT(*) = 1
) ba 
INNER JOIN book_tb b ON b.id = ba.book_id
INNER JOIN author_tb a ON a.id = ba.author_id
ORDER BY b.id

【讨论】:

  • 使用db<>fiddle (SQL Server) 验证,它正在工作。
  • 在第二种情况下,您可以通过添加到子选择 max(author_id) as author_id 来避免一次连接
  • 我会避免哪种加入?我仍然需要加入 author_tb 才能获得作者的姓名。
  • 我的意思是首先book_author_tb ba
【解决方案2】:

我会通过聚合来做到这一点:

SELECT b.title, b.summary, MAX(a.name) as name
FROM book_author_tb ba INNER JOIN
     book_tb b
     ON b.id = ba.book_id INNER JOIN
     author_tb a
     ON a.id = ba.author_id
GROUP BY b.title, b.summary
HAVING COUNT(*) = 1;

这个版本计算每本书的作者数量(假设没有重复,这是合理的)。

您的版本也由作者汇总。在这种情况下,count() 只会是“1”。

【讨论】:

    【解决方案3】:

    您应该在不同的子选择中计算您想要的过滤器的作者计数。所以从现在开始你可以在你的 WHERE 语句中使用它。

         SELECT b.title, b.summary, a.name FROM book_tb b
         JOIN book_author_tb ba ON b.id = ba.book_id
         JOIN author_tb a ON ba.author_id = a.author_id
         GROUP BY b.title, b.summary, a.name, b.id
         WHERE (SELECT count(ba.author_id) 
                    FROM book_author_tb
                    WHERE book_id = b.id) = 1
         ORDER BY b.id;
    

    【讨论】:

      猜你喜欢
      • 2013-10-19
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多