查询以获得每个项目的最高排名

Rod*_*d0n 2 sql postgresql postgresql-9.1

我是(简化)以下模型:

Book
  id
  name

BookCategory
  book_id
  category_id
  rank

Category
  id
  name
Run Code Online (Sandbox Code Playgroud)

对于给定的类别ID,我希望将具有该类别的书籍列为排名最高的类别.

我将举一个例子来说明它:

Book   

id    name   
---  -------
1     On Writing
2     Zen teachings
3     Siddharta

BookCategory   

book_id category_id      rank   
---       -------        -----
1        2               34.32
1        5               24.23
1        9               54.65
2        5               27.33
2        9               28.32
3        2               30.43
3        5               27.87

Category   

id    name   
---  -------
2     Writing
5     Spiritual
9     Buddism
Run Code Online (Sandbox Code Playgroud)

category_id = 2的结果将是id = 3的书.

这是我正在运行的查询:

SELECT book."name" AS bookname
FROM bookcategory AS bookcat
LEFT JOIN book ON bookcat."book_id" = book."id" 
LEFT JOIN category cat ON bookcat."category_id" = cat."id" 
WHERE cat."id" = 2
ORDER BY bookcat."rank"
Run Code Online (Sandbox Code Playgroud)

这不是正确的方法,因为它没有选择每本书的最高等级.我还没找到合适的解决方案.

注意:我正在使用postgresql 9.1版本.

编辑:

DB Schema(取自马丁的SQL小提琴答案):

create table Book (
  id int,
  name varchar(16)
  );

insert into Book values(1, 'On Writing');
insert into Book values(2, 'Zen teachings');
insert into Book values(3, 'Siddharta');

create table BookCategory (
  book_id int,
  category_id int,
  rank real
  );

insert into BookCategory values(1,2,34.32);
insert into BookCategory values(1,5,24.23);
insert into BookCategory values(1,9,54.65);
insert into BookCategory values(2,5,27.33);
insert into BookCategory values(2,9,28.32);
insert into BookCategory values(3,2,30.43);
insert into BookCategory values(3,5,27.87);

create table Category (
  id int,
  name varchar(16)
  );

insert into Category values(2, 'Writing');
insert into Category values(5,'Spiritual');
insert into Category values(9,    'Buddism');
Run Code Online (Sandbox Code Playgroud)

rs.*_*rs. 5

添加另一列来计算排名:

dense_rank() OVER (PARTITION BY book."name" ORDER BY bookcat."rank"
s ASC) AS rank
Run Code Online (Sandbox Code Playgroud)