Mar*_*cha 0 sql oracle postgresql
我有必须“分组”的数据。在每个结果组中,都有具有多个列的行,必须按如下方式处理:对于每个这样的给定列,返回非空的最新值。所以我必须对整个表进行“分组”(gb),并为每一列找到“max-like(NUM)”(下面表示为 NUM)。类似 max 的函数按时间列排序,下面表示为“时间”。换句话说,按 'gb' 分组,按 'time' 排序,最后 desc 为空,获取组中的第一项。
抱歉,这个复杂的描述。我希望一切都清楚。知道如何编写该 sql 查询(oracle/postgres)吗?
CREATE TABLE test (
gb integer,
NUM INTEGER,
time integer
);
--rows=groups, columns=time; so in first row=group data
--sorted by time are from left to right the middle value
--in triplet, thus, 2,1,3. Ie. most current non-null value in time is 3.
insert into test VALUES (1,2,1),(1,1,2),(1,3,3);--3
insert into test VALUES (2,1,1),(2,2,2),(2,3,3);--3
insert into test VALUES (3,3,1),(3,2,2),(3,1,3);--1
insert into test VALUES (4,3,1),(4,2,2),(4,null,3);--2
insert into test VALUES (5,2,1),(5,3,2),(5,null,3);--3
insert into test VALUES (6,2,1),(6,null,2),(6,null,3);--2
Run Code Online (Sandbox Code Playgroud)
询问
select
t.gb,
'<magic goes here>'
from test t
GROUP BY t.gb ORDER BY t.gb;
Run Code Online (Sandbox Code Playgroud)
预计会返回
1 | 3
2 | 3
3 | 1
4 | 2
5 | 3
6 | 2
Run Code Online (Sandbox Code Playgroud)
在Oracle中最简单的方法是:
SELECT gb, max(num) keep (DENSE_RANK LAST ORDER BY nvl2(num,time,NULL) NULLS first ) r
FROM test
GROUP BY gb
Run Code Online (Sandbox Code Playgroud)
还有一种“无组”方法:
SELECT DISTINCT gb, last_value(num ignore nulls)over(PARTITION BY gb ORDER BY time
RANGE BETWEEN UNBOUNDED preceding AND UNBOUNDED following) num
FROM test ORDER BY gb
Run Code Online (Sandbox Code Playgroud)
GB NUM
--- ----
1 3
2 3
3 1
4 2
5 3
6 2
Run Code Online (Sandbox Code Playgroud)