web-dev-qa-db-ja.com

各グループの最初のN行を選択する方法は?

次のような2つのSQLiteテーブルがあります。

 AuthorId | AuthorName
----------------------
 1        | Alice
 2        | Bob
 3        | Carol
 ...      | ....


 BookId | AuthorId | Title
----------------------------------
 1      | 1        | aaa1
 2      | 1        | aaa2
 3      | 1        | aaa3
 4      | 2        | ddd1
 5      | 2        | ddd2
 ...    | ...      | ...
 19     | 3        | fff1
 20     | 3        | fff2
 21     | 3        | fff3
 22     | 3        | fff4

タイトルごとに並べ替えて、各AuthorIdの最初のN(たとえば2)行を返すSELECTクエリを作成します(「各著者の最初の2冊の本を選択してください」)。

出力例:

 BookId |  AuthorId | AuthorName | Title
------------------------------------------
 1      |  1        |   Alice    | aaa1
 2      |  1        |   Alice    | aaa1
 4      |  2        |   Bob      | ddd1
 5      |  2        |   Bob      | ddd2
 19     |  3        |   Carol    | fff1
 20     |  3        |   Carol    | fff2

このクエリを作成するにはどうすればよいですか?

(はい、同様のトピックを見つけました。1行(最初または一番上)だけを返す方法を知っています。問題は2つです)。

23
Vladislav

相関サブクエリを使用してカウントできます。

_SELECT b.BookId, a.AuthorId, a.AuthorName, b.Title
FROM Author a join
     Book b
     on a.AuthorId = b.AuthorId
where (select count(*)
       from book b2
       where b2.bookId <= b.BookId and b2.AuthorId = b.AuthorId
      ) <= 2;
_

小さなデータベースの場合、これで問題ありません。 Book(AuthorId, BookId)で複合インデックスを作成すると、クエリに役立ちます。

17
Gordon Linoff

代替バリアントがあります:

SELECT * FROM (
    SELECT * FROM BOOK, AUTHOR
    WHERE BOOK.AUTHORID = AUTHOR.AUTHORID
) T1
WHERE T1.BOOKID IN (
    SELECT T2.BOOKID FROM BOOK T2
    WHERE T2.AUTHORID = T1.AUTHORID
    ORDER BY T2.BOOKTITLE
    LIMIT 2
)
ORDER BY T1.BOOKTITLE
14
fasked