从每组 sqlite 中选择前 n 条记录
Posted
技术标签:
【中文标题】从每组 sqlite 中选择前 n 条记录【英文标题】:select top n record from each group sqlite 【发布时间】:2015-03-23 00:56:45 【问题描述】:我正在尝试从如下所示的数据库表结果中选择前 2 条记录
SubjectId | StudentId | Levelid | total
------------------------------------------
1 | 1 | 1 | 89
1 | 2 | 1 | 77
1 | 3 | 1 | 61
2 | 4 | 1 | 60
2 | 5 | 1 | 55
2 | 6 | 1 | 45
我试过这个查询
SELECT rv.subjectid,
rv.total,
rv.Studentid,
rv.levelid
FROM ResultView rv
LEFT JOIN ResultView rv2
ON ( rv.subjectid = rv2.subjectid
AND
rv.total <= rv2.total )
GROUP BY rv.subjectid,
rv.total,
rv.Studentid
HAVING COUNT( * ) <= 2
order by rv.subjectid desc
但有些主题,例如缺少的地方,我什至尝试了以下链接的建议
How to select the first N rows of each group?
但我得到的每个 subjectid 多于两个
我做错了什么?
【问题讨论】:
HAVING COUNT( * ) <= 3
过滤掉任何包含 3 行或更多行的组。但是您并不是要排除整个组,而是要排除第二组之后的任何行。
HAVING COUNT( * ) <= 3
是错字,已更正
如果您提供所需输出的示例,则更容易提供答案。
【参考方案1】:
希望我能正确理解您的问题。让我知道这是否正确:
我重新创建了你的表:
CREATE TABLE stack (
SubjectId INTEGER(10),
StudentId INTEGER(10),
Levelid INTEGER(10),
total INTEGER(10)
)
;
插入的值
INSERT INTO stack VALUES
(1,1,1,89),
(1,2,1,77),
(1,3,1,61),
(2,4,1,60),
(2,5,1,55),
(2,6,1,45)
;
如果您尝试按 Levelid 获取***组(按总字段排序,假设 StudentID 作为主键):
SELECT *
FROM stack AS a
WHERE a.StudentID IN (
SELECT b.StudentID
FROM stack AS b
WHERE a.levelid = b.levelid
ORDER BY b.total DESC
LIMIT 2
)
;
产生这个结果:
SubjectId | StudentId | Levelid | total
1 | 1 | 1 | 89
1 | 2 | 1 | 77
SubjectId 前 2 名的示例,按总数排序:
SELECT *
FROM stack AS a
WHERE a.StudentID IN (
SELECT b.StudentID
FROM stack AS b
WHERE a.subjectID = b.subjectID
ORDER BY b.total DESC
LIMIT 2
)
;
结果:
SubjectId | StudentId | Levelid | total
1 | 1 | 1 | 89
1 | 2 | 1 | 77
2 | 4 | 1 | 60
2 | 5 | 1 | 55
我希望这就是您正在寻找的答案。
【讨论】:
好消息是它有效,坏消息是每 10K 记录执行需要 30 秒。【参考方案2】:您可以使用相关子查询:
select *
from ResultView rv1
where SubjectId || '-' || StudentId || '-' || LevelId in
(
select SubjectId || '-' || StudentId || '-' || LevelId
from ResultView rv2
where SubjectID = rv1.SubjectID
order by
total desc
limit 2
)
此查询通过连接三列来构造单列主键。如果你有一个真正的主键(比如ResultViewID
),你可以用它代替SubjectId || '-' || StudentId || '-' || LevelId
。
Example at SQL Fiddle.
【讨论】:
感谢您的回答,但我得到了不同的结果。我上面发布的示例是我的问题的简化版本,也许这就是原因。我将发布更详细的版本。我从中选择的表实际上是一个视图,它通过一个共同的 id 连接两个表。如果我想根据 levelid 选择这个结果,我应该把where
子句放在哪里?以上是关于从每组 sqlite 中选择前 n 条记录的主要内容,如果未能解决你的问题,请参考以下文章