From Oracle 11g, you can use this kind of requests:
with w(CompanyID, ChildID, transactionid, BatchID, Product_Details) as
(
select 'ABC', 'EFG', 306, null, 'Product1 ' from dual
union all
select 'ABC', 'EFG', 306, 54, 'Product2' from dual
union all
select 'ZXY', 'BFG', 405, 003, 'Product1' from dual
union all
select 'ZXY', 'BFG', 405, 004, 'Product2' from dual
union all
select 'ZXY', 'BFG', 407, null, 'Product3' from dual
)
select w.CompanyID,
w.ChildID,
max(w.transactionid) keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_transactionid,
max(w.batchid) keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_batchid,
max(w.Product_Details) keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_Product_Details
from w
group by w.CompanyID, w.ChildID
;
The nvl
function allows you to handle null cases. Here is the output (which does not fit yours, but I did the request as I understood what you wanted):
COMPANYID CHILDID MAX_TRANSACTIONID MAX_BATCHID MAX_PRODUCT_DETAILS
ABC EFG 306 54 Product2
ZXY BFG 407 Product3
EDIT: Let me try to explain further DENSE_RANK
and LAST
: inside a GROUP BY
, this syntax appears as an aggregate function (like SUM, AVG...).
- In a group, the
ORDER BY
gives the sorting (here, transactionid and batchid) - then the
DENSE_RANK LAST
states that you will focus on the last ranked row(s) of this sorting (you can have indeed several rows with same rank) - the
MAX
takes the maximum value inside these top-ranked rows. Most of the time, you only have one row soMAX
can appear useless, but it is not. So you will often seeMIN
andDENSE_RANK FIRST
, orMAX
andDENSE_RANK LAST
.
Here is the Oracle doc on this subject.