我有数据,我必须按'分组。在每个结果组中,存在具有多个列的行,必须对其进行处理:对于每个这样的给定列,返回非空的,最大的当前值。因此,我必须按照'(gb)整个表格进行分组,然后找到类似max(NUM)'对于每一列(以下表示为NUM)。 max-like函数按时间列排序,下面表示为' time'。换句话说,按' gb'分组,按时间排序' desc nulls last,获取组中的第一项。
对不起,对于那个错综复杂的描述。我希望它清楚。知道怎么写那个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
查询
select
t.gb,
'<magic goes here>'
from test t
GROUP BY t.gb ORDER BY t.gb;
预计将返回
1 | 3
2 | 3
3 | 1
4 | 2
5 | 3
6 | 2
答案 0 :(得分:3)
在Oracle中,最简单的方法是:
SELECT gb, max(num) keep (DENSE_RANK LAST ORDER BY nvl2(num,time,NULL) NULLS first ) r
FROM test
GROUP BY gb
还有一个&#34;无团体&#34;的方法:
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
GB NUM
--- ----
1 3
2 3
3 1
4 2
5 3
6 2
答案 1 :(得分:2)
您可以使用row_number
为具有相同gb
的每一行分配一个递增的数字。按time
排序这些行,只显示第一行:
select gb
, num
from (
select row_number() over (partition by gb order by time desc) rn
, *
from test
where num is not null
) sub
where rn = 1 -- Row with highest time per (gb) group
答案 2 :(得分:0)
这可能是适用于Oracle和PostgreSQL的最简单的解决方案:
SELECT DISTINCT
gb,
first_value(num) OVER (PARTITION BY gb ORDER BY time DESC)
FROM test
WHERE num IS NOT NULL
ORDER BY gb;
答案 3 :(得分:0)
以下是标准SQL中的解决方案:
with grp as
(
select distinct gb from mytable
)
SELECT
gb,
(
select num
from mytable m
where m.gb = grp.gb and m.num is not null
order by thetime desc
fetch first row only
) as n
FROM grp
order by grp.gb\\
每列需要一个这样的子查询。
在Oracle中,此查询仅适用于版本12c;以前的版本没有FETCH FIRST n ROWS
子句。
这是另一种标准SQL,它可以在较旧的Oracle版本中运行:
with grp as
(
select distinct gb from mytable
)
SELECT
gb,
(
select num
from mytable m
where m.gb = grp.gb and thetime =
(
select max(thetime)
from mytable m2
where m2.gb = m.gb and m2.num is not null
)
) as n
FROM grp
order by grp.gb\\
Rextester演示:http://rextester.com/QUO91858