我有(简化)以下模型:
Book
id
name
BookCategory
book_id
category_id
rank
Category
id
name
对于给定的类别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
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"
这不是正确的方法,因为它没有选择每本书的最高等级。我还没有找到合适的解决方案。
注意:我正在使用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');
答案 0 :(得分:5)
添加另一列来计算排名:
dense_rank() OVER (PARTITION BY book."name" ORDER BY bookcat."rank"
s ASC) AS rank
答案 1 :(得分:1)
这是你想要的吗?
SELECT
book.name, mx.max_rank
FROM
(SELECT
max(rank) AS max_rank , book_id
FROM BookCategory WHERE category_id = 2
GROUP BY
book_id
) mx
JOIN Book ON
mx.book_id = Book.id
如果我理解你的问题,你需要获得BookCategory中每本书的给定类别的最大值(这是内部选择所做的),然后简单地将它加入book_id上的Book表。
整个示例位于SQL Fiddle
编辑:
我看到已经有一个已接受的答案,但为了完整起见,这是我在澄清问题后的答案:
SELECT
Book.name
FROM
(SELECT max(rank) AS max_rank, book_id AS bid
FROM BookCategory GROUP BY book_id
) mx
JOIN BookCategory ON
rank = max_rank
AND book_id = bid
JOIN Book
ON book_id = Book.id
WHERE category_id = 2
答案 2 :(得分:1)
设置:
CREATE TABLE Book
(
id int PRIMARY KEY,
name text not null
);
CREATE TABLE Category
(
id int PRIMARY KEY,
name text not null
);
CREATE TABLE BookCategory
(
book_id int,
category_id int,
rank numeric not null,
primary key (book_id, category_id)
);
INSERT INTO Book VALUES
(1, 'On Writing'),
(2, 'Zen teachings'),
(3, 'Siddharta');
INSERT INTO Category VALUES
(2, 'Writing'),
(5, 'Spiritual'),
(9, 'Buddism');
INSERT INTO BookCategory VALUES
(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);
解决方案:
SELECT Book.name
FROM (
SELECT DISTINCT ON (book_id)
*
FROM BookCategory
ORDER BY book_id, rank DESC
) t
JOIN Book ON Book.id = t.book_id
WHERE t.category_id = 2
ORDER BY t.rank;
逻辑上,FROM
子句中的子查询会为每本书生成与排名最高类别的关系,然后您可以从中选择该类别中的书籍,并按该类别中的排名进行排序。
结果:
name ----------- Siddharta (1 row)