为 MySQL table 中的各行查找两个最大值
FInd two highest values for various rows in MySQL table
我有一个 MySQL table,sales,内容如下:
+----+-------+--------+
| id | name | amount |
+----+-------+--------+
| 1 | Alice | 12 |
| 2 | Bob | 10 |
| 3 | Alice | 14 |
| 4 | Bob | 2 |
| 5 | Alice | 6 |
| 6 | Bob | 23 |
| 7 | Bob | 5 |
| 8 | Alice | 12 |
+----+-------+--------+
对于每个 name 我想找到具有最高 amount 的两行。换句话说,我想要一个 returns 这个结果的查询:
+----+-------+--------+
| id | name | amount |
+----+-------+--------+
| 3 | Alice | 14 |
| 1 | Alice | 12 |
| 6 | Bob | 23 |
| 2 | Bob | 10 |
+----+-------+--------+
(结果中只应包括第 1 行和第 8 行之一。哪一个都无关紧要。)
我该怎么做?
编辑
添加了 table 中的第 8 行以阐明平局的处理。
如果你是运行 MySQL 8.0,只需使用window函数:
select *
from (
select s.*,
rank() over(partition by name order by amount desc) rn
from sales s
) s
where rn <= 2
order by name, amount desc
这允许前 2 个关系(如果有)。
在早期版本中,一个选项使用子查询进行过滤:
select *
from sales s
where (select count(*) from sales s1 where s1.name = s.name and s1.amount > s.amount) < 2
order by name, amount desc
如果您使用的是现代 MySQL,row_number
应该就是您要找的。
select
row_number() over (partition by [name] order by [amount] desc]) [rank],
id,
name,
amount
这会添加必要的“排名”列,因此您只需 SELECT 来自 SELECT 作为您的 table 来源:
select id, name, amount
from ( -- the above query
select
row_number() over (partition by [name] order by [amount] desc]) [rank],
id,
name,
amount
) x
where x.[rank] <= 2
order by [name], [amount] desc
这是吹捧。
旧版本 MySQL 中的一个简单方法是:
select t.*
from t
where t.amount >= (select t2.amount
from t t2
where t2.name = t.name
order by t2.amount desc
limit 1 offset 1
);
使用 (name, amount)
上的索引,这可能是最快的方法。
我有一个 MySQL table,sales,内容如下:
+----+-------+--------+
| id | name | amount |
+----+-------+--------+
| 1 | Alice | 12 |
| 2 | Bob | 10 |
| 3 | Alice | 14 |
| 4 | Bob | 2 |
| 5 | Alice | 6 |
| 6 | Bob | 23 |
| 7 | Bob | 5 |
| 8 | Alice | 12 |
+----+-------+--------+
对于每个 name 我想找到具有最高 amount 的两行。换句话说,我想要一个 returns 这个结果的查询:
+----+-------+--------+
| id | name | amount |
+----+-------+--------+
| 3 | Alice | 14 |
| 1 | Alice | 12 |
| 6 | Bob | 23 |
| 2 | Bob | 10 |
+----+-------+--------+
(结果中只应包括第 1 行和第 8 行之一。哪一个都无关紧要。)
我该怎么做?
编辑
添加了 table 中的第 8 行以阐明平局的处理。
如果你是运行 MySQL 8.0,只需使用window函数:
select *
from (
select s.*,
rank() over(partition by name order by amount desc) rn
from sales s
) s
where rn <= 2
order by name, amount desc
这允许前 2 个关系(如果有)。
在早期版本中,一个选项使用子查询进行过滤:
select *
from sales s
where (select count(*) from sales s1 where s1.name = s.name and s1.amount > s.amount) < 2
order by name, amount desc
如果您使用的是现代 MySQL,row_number
应该就是您要找的。
select
row_number() over (partition by [name] order by [amount] desc]) [rank],
id,
name,
amount
这会添加必要的“排名”列,因此您只需 SELECT 来自 SELECT 作为您的 table 来源:
select id, name, amount
from ( -- the above query
select
row_number() over (partition by [name] order by [amount] desc]) [rank],
id,
name,
amount
) x
where x.[rank] <= 2
order by [name], [amount] desc
这是吹捧。
旧版本 MySQL 中的一个简单方法是:
select t.*
from t
where t.amount >= (select t2.amount
from t t2
where t2.name = t.name
order by t2.amount desc
limit 1 offset 1
);
使用 (name, amount)
上的索引,这可能是最快的方法。