postgresql 根据要筛选的列的值进行联接和分组

c8ib6hqw  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(4)|浏览(102)

假设我有两个包含这些数据的表:

author
id | name
---------
1  | John
2  | Jack
3  | James
4  | Bob
5  | Gorge

book
id | author_id | title  | state
-------------------------------------
1  | 1         | book_1 | published
2  | 1         | book_2 | pre-published
3  | 1         | book_3 | published
4  | 1         | book_4 | rejected
5  | 2         | book_5 | published
6  | 3         | book_6 | rejected
7  | 3         | book_7 | pre-published
8  | 4         | book_8 | rejected

字符串
我想要的是一个sql查询,它给我每个作者的id和名称以及出版的书的数量,即使他们出版了0。我想这可能是一个简单的查询,但我坚持了下来,我想要的是:

id | name   | num_of_published_books
------------------------------------
1  | John   |          2
2  | Jack   |          1
3  | James  |          0
4  | Bob    |          0
5  | Gorge  |          0


我能够获取前两行JohnJack。我还可以根据author_idstate对它们进行分组。但这不是我想要的
注意,我不想使用子查询。

vs3odd8k

vs3odd8k1#

SELECT
  a.id AS author_id,
  a.name,
  COUNT(b.state = 'published' OR NULL) AS num_of_published_books
FROM
  author a
LEFT JOIN
  book b ON a.id = b.author_id
GROUP BY
  a.id, a.name;

字符串
希望对你有帮助。

  1. b.state = 'published',我们可以过滤掉已经出版的书,结果是false(0)或者true(1)
  2. OR NULL是在前一步骤的结果为false(0)时得到NULL。在我的记忆中,当使用OR运算符比较非空值和NULL值时,结果总是NULLCOUNT将忽略NULL
    1.有两种可能的结果:true(1) OR NULLfalse(0) OR NULL,它们的结果分别是true(1)NULL
    1.最后,Count计算不是NULL的数字。
ibps3vxo

ibps3vxo2#

SELECT author.id, author.name, 
       COALESCE(COUNT(CASE state  
                         WHEN 'published' THEN 1 
                         ELSE O 
                      END), 0)) as num_of_published_books
FROM   author
       LEFT OUTER JOIN book
          ON author.id = book.author_id
GROUP BY author.id, author.name

字符串

3ks5zfa0

3ks5zfa03#

为了达到预期的效果,您可以在SQL查询中使用LEFT JOINGROUP BY
LEFT JOIN确保包含“author”表中的所有作者,即使他们在“book”表中没有相应的记录。
下面是应该给予你预期结果的SQL查询:

SELECT a.id,a.name,
  COALESCE(SUM(CASE WHEN b.state = 'published' THEN 1 ELSE 0 END), 0) AS num_of_published_books
FROM author a LEFT JOIN book b ON a.id = b.author_id
GROUP BY a.id, a.name;

字符串
检查查询结果http://sqlfiddle.com/#!9/0db9c8a/1/0

**说明:**查询使用LEFT JOIN根据author_id合并author和book表,然后使用SUM函数和CASE语句统计每个作者的已出版图书数量(1表示'published',0表示其他)。COALESCE用于处理NULL值,并在作者没有出版书籍的情况下将其替换为0。

mf98qq94

mf98qq944#

另一个使用聚合和FILTER的版本。

select a.id, min(a.name) as name, 
       count(*) filter (where state = 'published') as num_of_published_books
from author a left outer join book b on a.id = b.author_id
group by a.id;

字符串
请注意,如果author.id是主键,则min(a.name)可以简单地变为a.name
DB Fiddle

相关问题