假设我有以下数据:
| f1 | f2 | f3 |
|----|----|----|
| 1 | 1 | 1 |
| 1 | 1 | 5 |
| 1 | 2 | 3 |
| 1 | 2 | 6 |
| 1 | 3 | 4 |
| 1 | 3 | 7 |
| 2 | 1 | 2 |
| 2 | 1 | 22 |
| 2 | 2 | 3 |
| 2 | 2 | 4 |
每个 f1、f2 组合有两个最大的 f3 值。
对于这个特定示例,我想获得每个 f1 和范围(f2 - 每个 f1 的 max(f2))的前 2 个最小值。
示例输出:
| f1 | RNG| f3 |
|----|----|----|
| 1 |1 -3| 1 |
| 1 |1 -3| 3 |
| 1 |2 -3| 3 |
| 1 |2 -3| 4 |
| 1 |3 -3| 4 |
| 1 |3 -3| 7 |
| 2 |1- 2| 2 |
| 2 |1- 2| 3 |
| 2 |2- 2| 3 |
| 2 |2- 2| 4 |
不需要创建字段 RNG。我添加它只是为了表明 forf1=1
有 3 个范围:1-3, 2-3, 3-3
由 for 的不同值f2
创建f1=1
。对于每个这样的范围,我想计算每个 f1 和范围的前 k 个最小值。
SQL小提琴在这里:
http://sqlfiddle.com/#!15/9ddbb/1
构建范围可以通过以下方式完成:
SELECT DISTINCT s1.f1,s1.f2 AS range_from ,s2.f2 AS range_to
FROM dbTable s1,
(SELECT f1,MAX(f2) AS f2 FROM dbTable
GROUP BY f1) s2
WHERE s1.f1=s2.f1
ORDER BY s1.f1,s1.f2;
有没有办法在不构建中间数据库表的情况下实现这一目标?
另一种方式,使用
LATERAL
9.3+ 版本可用的语法:在SQLfiddle测试。
或者没有 CTE:
我认为这个查询是正确的:
并且似乎在SQL Fiddle中给出了正确的输出: