3

私は(簡略化された)次のモデルを持っています:

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"

これは、各本の最大ランクを選択しないため、これを行う正しい方法ではありません。私はまだ適切な解決策を見つけていません。

注:私はpostgresql9.1バージョンを使用しています。

編集:

DBスキーマ(martinのSQL Fiddleの回答から取得):

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');
4

3 に答える 3

5

ランクを計算するために別の列を追加します。

dense_rank() OVER (PARTITION BY book."name" ORDER BY bookcat."rank"
s ASC) AS rank
于 2012-08-08T15:41:07.290 に答える
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フィドルにあります

編集:

すでに受け入れられている答えがあるようですが、完全を期すために、質問を明確にした後の私の答えを次に示します。

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

SQLフィドルについて。

于 2012-08-08T15:59:43.963 に答える
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各本の最高ランクのカテゴリとの関係を生成し、そこからそのカテゴリの本を選択して、そのカテゴリのランク順に並べ替えます。

結果:

   名前    
-----------
 シッダールタ
(1行)
于 2012-08-08T17:36:33.527 に答える