I have two tables (requests and requests_details) like as shown below. requests table have request_id and request name and requests_details have the details whether the request is in pending, approved or rejected. I have implemented the below two tables in one to many mapping using Spring JPA. In requests_details table if there is second entry apart from PENDING status for a request then it means from the status we can know if the request is approved or a rejected one
Now I have a requirement to get all the pending and approval requests separately
I have wrote the hql query like as shown below
For getting all the pending requests
SELECT request.name, details.*
FROM requests request JOIN request_details details ON request.request_id=details.request_id
WHERE
details.status = "PENDING" AND
details.status !="APPROVED" OR details.status !="REJECTED"
but for the above query it is returning all the requests
For getting all the approved requests
SELECT request.name, details.*
FROM requests request JOIN request_details details ON request.request_id=details.request_id
WHERE
details.status = "PENDING" AND
details.status ="APPROVED"
but for the above query it is not returning any requests
My expected result is as give below
Can anyone please help me on this
What is happening in the first query is that you are stating that the status should be "PENDING" and not "APPROVED" (this covers "REJECTED") or not "REJECTED" (this covers all other cases) that is why you get everything.
If you are trying to get all "PENDING" then just simply
SELECT
request.id,
details.*
FROM requests request
JOIN request_details details ON request.request_id = details.request_id
WHERE details.status = "PENDING"
AND (SELECT count(*) FROM requests_details
WHERE requests_details.request_id = request.request_id) = 1
The subquery makes sure there is only one entry for the request meaning it is only "PENDING" and has not be approved or rejected.
In the second case you are getting nothing back because you are stating that the status should be "PENDING" and "APPROVED" at the same time and that will always be false.
If you want to get entries that are both "PENDING" and "APPROVED" then you can do something like this
SELECT
request.request_id,
details.*
FROM requests request
JOIN requests_details details ON request.request_id = details.request_id
WHERE details.status = 'PENDING'
AND (SELECT count(*) FROM requests_details
WHERE requests_details.request_id = request.request_id
AND requests_details.status = 'APPROVED'
) = 1
What happens is that you find all "PENDING" requests and then make sure those are also "APPROVED". This is done with the subquery. There you only need to know that the record with the right id and the "APPROVED" status exists, that is why you would use the count, the data you already have from the previous part.
NOTE: It would be a good idea to update the status of requests from "PENDING" to "APPROVED" or "REJECTED" rather than inserting a new record. This would be safer and queries would be more simple and faster (you wouldn't need the subquery). It would also avoid possible bugs where requests end up having multiple conflicting statuses.