2013-08-01 71 views
19

我有两个SQLite的表是这样的:如何选择每组的前N行?

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 

我想打一个SELECT查询将返回第N(例如两个)行每个AUTHORID,按标题排序(“选择的前两本图书每个作者“)。

输出示例:

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 

如何建立这个查询?

(是的,我找到了一个类似的话题,我知道如何返回只有一行(第一或顶部)。

+0

有人在这里遇到过类似问题http://stackoverflow.com/questions/9518900/how-to-find-teams-with-sql-command –

+0

请参见[56,“问题包括‘标签中的’他们标题?“](http://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles),其中的共识是”不,他们不应该“! –

回答

12

可以使用相关子查询执行计数:

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)上创建组合索引,那么这将有助于查询。

13

有替代变型:

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 
+0

我喜欢这个答案更适合我的情况,但MySQL不支持在子查询中的“限制”,所以我不得不与其他解决方案一起去...... :(upvoted无论如何:) – msb

0

在这里你去。可能为时已晚,但我刚刚看到帖子。您可以更改< = 2以匹配您需要的n。

SELECT 
a.authorid, 
a.authorname, 
b.bookid, 
b.booktitle 
FROM author a 
JOIN book b ON b.authorid = b.authorid 
QUALIFY ROW_NUMBER() OVER (PARTITION BY a.authorid 
ORDER BY b.booktitle ASC) <=2 
+2

这不符合'限定'作为SQLite的答案:-) – user1735003