这很困难:我将数据以这种形式返回到临时表foo
中:
id n v
-- - -
1 3 1
1 3 10
1 3 100
1 3 201
1 3 300
2 1 13
2 1 21
2 1 300
4 2 1
4 2 7
4 2 19
4 2 21
4 2 300
8 1 11
按id
分组,我需要基于v
中的值获取n
的第n个最低值的行。例如,对于ID为1的组,我需要获取v
等于100的行,因为100是v
的第三低值。
最终结果如下所示:
id n v
-- - -
1 3 100
2 1 13
4 2 7
8 1 11
有关数据的一些注释:
n
对于具有给定ID的每一行将始终相同n
永远不会大于具有该ID的行数id
,然后按v
如果您可以使用通用SQL而不是特定于oracle的东西来完成奖励,那不是必须的(我怀疑rownum
可能在任何解决方案中都占主导地位)。这是我的尝试,但是在得到可行的解决方案之前,我最终使自己感到困惑。
答案 0 :(得分:2)
使用窗口功能
select * from
(
select t.*, row_number() over(partition by id ,n order by v) as rn
from foo t
) t1
where t1.rn=t1.n
因为ops样本输出只需要第三高的值,所以我把条件t1.rn = 3放在哪里,尽管根据描述它应该是t1.rn = t1.n
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=65abf8d4101d2d1802c1a05ed82c9064
答案 1 :(得分:2)
我将使用row_number
函数将行号与n
中的CTE
列值进行比较,再进行一次CTE
以按v
进行行号排序描述
获取rn = 1
,它是n
数字组中的平均最大值。
CREATE TABLE foo(
id int,
n int,
v int
);
insert into foo values (1,3,1);
insert into foo values (1,3,10);
insert into foo values (1,3,100);
insert into foo values (1,3,201);
insert into foo values (1,3,300);
insert into foo values (2,1,13);
insert into foo values (2,1,21);
insert into foo values (2,1,300);
insert into foo values (4,2,1);
insert into foo values (4,2,7);
insert into foo values (4,2,19);
insert into foo values (4,2,21);
insert into foo values (4,2,300);
insert into foo values (8,1,11);
查询1 :
with cte as(
select id,n,v
from
(
select t.*, row_number() over(partition by id ,n order by n) as rn
from foo t
) t1
where rn <= n
), maxcte as (
select id,n,v, row_number() over(partition by id ,n order by v desc) rn
from cte
)
select id,n,v
from maxcte
where rn = 1
Results :
| ID | N | V |
|----|---|-----|
| 1 | 3 | 100 |
| 2 | 1 | 13 |
| 4 | 2 | 7 |
| 8 | 1 | 11 |
答案 2 :(得分:2)
如果您的数据库版本是12.1或更高版本,那么有一个更简单的解决方案:
SELECT DISTINCT ID, n, NTH_VALUE(v,n) OVER (PARTITION BY ID) AS v
FROM foo
ORDER BY ID;
| ID | N | V |
|----|---|-----|
| 1 | 3 | 100 |
| 2 | 1 | 13 |
| 4 | 2 | 7 |
| 8 | 1 | 11 |
根据实际数据,您可能必须添加ORDER BY n
子句和/或windowing_clause作为RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
,请参见NTH_VALUE