Return 按字段分组时的所有数据

Return all data when grouping on a field

我有以下2张表(真实表的字段比较多):

create table publisher(id serial not null primary key,
name text not null);

create table product(id serial not null primary key,
name text not null,
publisherRef int not null references publisher(id));

示例数据:

insert into publisher (id,name) values (1,'pub1'),(2,'pub2'),(3,'pub3');
insert into product (name,publisherRef) values('p1',1),('p2',2),('p3',2),('p4',2),('p5',3),('p6',3);

我想查询 return:

name, numProducts
pub2, 3
pub3, 2
pub1, 1

产品由出版商出版。现在我需要一个列表,其中包含至少拥有一种产品的所有发布商的名称和 ID,按每个发布商拥有的产品总数排序。

我可以通过以下方式获取按产品数量排序的发布商的 ID:

select publisherRef AS id, count(*)
from product
order by count(*) desc;

但我还需要结果中每个出版商的名称。我想我可以使用像这样的子查询:

select *
from publisher
where id in (
   select publisherRef
   from product
   order by count(*) desc)

但子查询中的行顺序在外部 SELECT.

中丢失

有什么方法可以通过单个 sql 查询来实现吗?

SELECT pub.name, pro.num_products
FROM  (
   SELECT publisherref AS id, count(*) AS num_products
   FROM   product
   GROUP  BY 1
   ) pro
JOIN   publisher pub USING (id)
ORDER  BY 2 DESC;

db<>fiddle here

或者(因为标题提到“所有数据”)return 发布者的所有列 pub.*。在子查询中聚合产品后,您可以自由地在外部 SELECT.

中列出任何内容

这只列出发布商

have at least one product

结果按

排序

the total number of products each publisher has

在 加入“1”-table 之前聚合“n”-table 通常会更快。然后使用 [INNER] JOIN(而不是 LEFT JOIN)排除没有产品的发布商。

请注意,IN 表达式(或给定列表 - there are two syntax variants 中的项目)中的行顺序无关紧要。

publisherref AS id 中的列别名完全是可选的,以便在以下连接条件中对相同的列名称使用更简单的 USING 子句。

旁白:避免在 Postgres 中使用 CaMeL-case 名称。专门使用不带引号的合法小写名称,让您的生活更轻松。