问题描述
我需要从单列中有限数量的行中找到一个最小值。假设我有这个results
表:
-----------------------------------------
| id | category | class | score |
-----------------------------------------
| 1 | contest1 | seven | 55 |
| 2 | contest1 | sixth | 78 |
| 3 | contest2 | seven | 20 |
| 4 | contest1 | eleven | 21 |
| 5 | contest2 | eleven | 56 |
| 6 | contest3 | ten | 66 |
| 7 | contest3 | ten | 90 |
| 8 | contest3 | nine | 91 |
| 9 | contest2 | seven | 30 |
| 10 | contest1 | nine | 51 |
-----------------------------------------
现在,我需要创建一组值,这些值> = 50并且限制为3行。像这样:
-----------------------------------------
| id | category | class | score |
-----------------------------------------
| 1 | contest1 | seven | 55 |
| 2 | contest1 | sixth | 78 |
| 10 | contest1 | nine | 51 |
-----------------------------------------
在这个集合中,我必须找到MIN值,实际上这很简单,但前提是要针对每个类别手动进行设置。此查询工作完美:
SELECT MIN(t1.score)
FROM (
SELECT category,score
FROM results
WHERE category = "contest1" AND score >= 50
ORDER BY score DESC
LIMIT 3
) t1
给出正确的结果:
-------------------
| MIN(t1.score) |
-------------------
| 51 |
-------------------
但是,我无法编写一个查询来自动对每个类别进行查询。在真实表中,有一百多个类别,具有数千个得分值。如何在有限的行集中找到每个类别的最小值?
解决方法
使用row_number()
获取每个类别的“前”三行:
select r.*
from (select r.*,row_number() over (partition by category order by sid) as seqnum
from results r
where score >= 50
) r
where seqnum <= 3;
这将根据每个类别的id
返回前三行。然后,您可以获取最小值:
select category,min(score)
from (select r.*,row_number() over (partition by category order by sid) as seqnum
from results r
where score >= 50
) r
where seqnum <= 3
group by category;
,
您的行数不足以产生影响。
但是它也使用rwo数获得每个类别的3个最小分数,大于50分
CREATE TABLE results ( `id` INTEGER,`category` VARCHAR(8),`class` VARCHAR(6),`score` INTEGER ); INSERT INTO results (`id`,`category`,`class`,`score`) VALUES ('1','contest1','seven','55'),('2','sixth','78'),('3','contest2','20'),('4','eleven','21'),('5','56'),('6','contest3','ten','66'),('7','90'),('8','nine','91'),('9','30'),('10','51');
SELECT `id`,`score` FROM(SELECT IF(`category` = @cat,@rown := @rown + 1,@rown := 1) rownum,`id`,@cat := `category` 'category',`score` FROM (SELECT * FROM results ORDER By `category`,`score` )r1,(SELECT @rown := 0,@cat := '') t1 WHERE `score` > 50 ) t1 WHERE rownum < 4
id | category | class | score -: | :------- | :----- | ----: 10 | contest1 | nine | 51 1 | contest1 | seven | 55 2 | contest1 | sixth | 78 5 | contest2 | eleven | 56 6 | contest3 | ten | 66 7 | contest3 | ten | 90 8 | contest3 | nine | 91
db 提琴here