请求实现从给定数据表中提取两个最大值的技术方案
解决按Item提取两个最高价格记录的问题
嘿,看你卡在从数据表提取每个item的两个最高价格记录上了,我来帮你理清楚解决方案!
先把你的原始数据整理成清晰的表格方便查看:
| item | loc | price | START_DATE | CALC_DATE |
|---|---|---|---|---|
| item1 | 1243 | 1,16 | 18.04.16 | 18.04.13 |
| item1 | 1243 | 1,20 | 18.02.20 | 18.02.19 |
| item1 | 1243 | 1,20 | 18.02.17 | 18.02.16 |
| item1 | 1243 | 1,20 | 18.02.15 | 18.02.14 |
| item1 | 1243 | 1,18 | 18.01.10 | 18.01.09 |
| item2 | 1243 | 2,23 | 18.03.20 | 18.03.19 |
| item2 | 1243 | 2,77 | 18.02.27 | 18.02.26 |
| item2 | 1243 | 2,42 | 18.01.24 | 18.01.23 |
| item2 | 1243 | 3,21 | 18.01.05 | 18.01.04 |
| item2 | 1243 | 2,77 | 18.01.04 | 18.01.03 |
接下来分两种常见需求给你解决方案:
需求1:每个Item最多取2条记录(即使有价格并列,只选2条)
这种情况用ROW_NUMBER()窗口函数,它会给每个item组内的行分配唯一序号,价格相同的话按数据库默认排序取前2条:
WITH ranked_prices AS ( SELECT *, -- 把逗号替换成点,转成数值型再排序,避免字符串排序的坑 ROW_NUMBER() OVER (PARTITION BY item ORDER BY REPLACE(price, ',', '.') DESC) AS price_rank FROM your_table_name -- 替换成你的实际表名 ) SELECT item, loc, price, START_DATE, CALC_DATE FROM ranked_prices WHERE price_rank <= 2;
输出示例(item部分):
- item1:两条
1,20的记录(具体哪两条取决于数据库内部排序) - item2:
3,21和一条2,77的记录
需求2:提取所有属于前2个最高价格的记录(包含并列)
如果想要保留所有价格为最高和第二高的记录(比如item1的三条1,20都算最高,要全部保留),用DENSE_RANK()窗口函数,它会给相同价格的行分配相同的序号,且序号连续:
WITH ranked_prices AS ( SELECT *, DENSE_RANK() OVER (PARTITION BY item ORDER BY REPLACE(price, ',', '.') DESC) AS price_rank FROM your_table_name -- 替换成你的实际表名 ) SELECT item, loc, price, START_DATE, CALC_DATE FROM ranked_prices WHERE price_rank <= 2;
输出示例(item部分):
- item1:三条
1,20+ 一条1,18的记录 - item2:
3,21+ 两条2,77的记录
关键注意点:
你的price字段用逗号做小数点分隔,排序时一定要替换成点转成数值型,否则字符串排序可能会出问题(比如1,100字符串排序会比1,20靠后,但数值上其实更大)。
内容的提问来源于stack exchange,提问作者tech_guy
相关产品推荐
相关产品推荐

