在有限集中查找MIN值

问题描述

我需要从单列中有限数量的行中找到一个最小值。假设我有这个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