In a Java application based on an Oracle SQL database, I have the following problem to solve:
An entity DataDelivery
can consist of any number of Packet
.
Packet
has a PacketStatus
and the the foreign key datadeliveryid
.
PacketStatus
is an Enum with the values:
0, processed
1, processing
2, error
3, waiting
The numeric value is stored in the column PacketStatus
in table PACKET.
In my view, I want to display the DataDelivery
as table rows including a column that displays the combined status of all pertaining packets. The combined status of the Packets shall be determined according to the logic below:
If any one Packet pertaining to a DataDelivery has the status 'error': View column shall display 'error'.
If any one Packet pertaining to a DataDelivery has the status 'waiting': View column shall display 'waiting'.
If all Packets pertaining to a DataDelivery have the status 'processed': View column shall display 'processed'.
If all Packets pertaining to a DataDelivery have the status 'processing': View column shall display 'processing'.
If all Packets pertaining to a DataDelivery have either the status 'processed' or 'processing': View column shall display 'processing'.
In all other cases the view column shall display: 'error'.
count
ignores null
s. You can use this fact to perform a count
over a case
expression to count how many of the packets are in which status. From there on, it's a matter of gluing everything together with case
s:
SELECT dd.*, status
FROM DataDelivery dd
JOIN (SELECT dataDeliveryId,
CASE WHEN COUNT(CASE status WHEN 2 THEN 1 END) > 0 THEN 'error'
WHEN COUNT(CASE status WHEN 3 THEN 1 END) > 0 THEN 'waiting'
WHEN COUNT(CASE status WHEN 0 THEN 1 END) = COUNT(*) THEN 'processed'
WHEN COUNT(CASE status WHEN 1 THEN 1 END) = COUNT(*) THEN 'processing'
ELSE 'error' END AS status
FROM packet
GROUP BY dataDeliveryId) p ON dd.dataDeliveryId = p.dataDeliveryId