Использовать оконные функции:
select t.*
from (select t.*,
sum(case when blocknumber is not null then 1 else 0 end) over (partition by documentref) as num_bn_notnull,
rank() over (partition by documentref
order by (case when blocknumber is not null then documentid end) desc nulls last
) as rnk
from t
) t
where num_bn_notnull = 0 or
rnk = 1;
Или вы можете использовать exists
предложения:
select t.*
from t
where not exists (select 1
from t t2
where t2.documentref = t.documentref and
t2.blocknumber is not null
) or
t.documentid = (select max(t2.documentid)
from t t2
where t2.documentref = t.documentref and
t2.blocknumber is not null
);
Это может использовать индекс на (documentref, blocknumber, documentid)
.
На самом деле, по причуде языка SQL, я думаю, что это также работает:
select t.*
from t
where t.documentid >= any (select t2.documentid
from t t2
where t2.documentref = t.documentref and
t2.blocknumber is not null
order by t2.documentid
fetch first 1 row only
);
Подзапрос возвращает пустой набор, если все blocknumber
s NULL
. По определению, любой идентификатор документа соответствует условию в пустом наборе.