For me the scenario is hard to explain, but I would like to get a list of users (actually “patients”) which are ready for a dismissal meeting.
THE SITUATION
I have a patient table:
PATIENT
id (int)
name (varchar)
The patient follows a special process, where I have defined phases:
PHASE
id (int)
name (varchar)
And I log all the phases of the patient:
STATUS
id (int)
phase_id (int)
patient_id (int)
timestamp (datetime)
The term “ready for a meeting” means the meeting is planned. Such planned meetings are logged in a message table. The message for a planned meeting has a type “meeting_planned” and for example when the meeting is done, there is a new message “meeting_done”.
MESSAGE
id (int)
patient_id (int)
type (enum)
value (varchar)
timestamp (datetime)
MY QUERY
I am looking for a query now which I really cannot come up with. My logic is:
- Select all patients;
- Where the last status (based on timestamp) is from phase name “C” or “D”;
- Where there is no message with the type meeting_planned.
Ad 2: the patient can be either in one of the two phases. When a patient is in phase A, B, E or F then a meeting cannot be planned. A nurse may decide to plan the meeting already when patient is in phase C, but if that did not happened, it will occur at phase D (D always follows C, it is A>B>C>D>E>F).
Ad 3: there might be other messages, but never with this type. There is a unique constaint here on type+patient_id. If a meeting has been planned and has happened, there are two messages (type 1 = meeting_planned, type 2 = meeting_done). If there hasn’t been a meeting planned, the type meeting_planned does not occur, but other messages might be set already.
WHAT HAVE I TRIED
I came up with this query now:
SELECT p.id, p.name, ph.name
FROM patient p
LEFT JOIN status s ON p.id=s.patient_id
LEFT JOIN phase ph ON ph.id=s.phase_id
LEFT JOIN message m ON p.id=m.patient_id
WHERE (ph.name='C' OR ph.name='D')
AND (ph.name != 'E')
AND (m.type != 'meeting_planned' OR m.type IS NULL)
MY QUESTIONS
In above query I have two things I cannot manage:
- I have patients double in the list. Any patient in phase D also occurs as a patient in phase C (so double). I tried a
SELECT DISTINCTbut that didn’t work out - I now exclude phases based on their name, but I would like to order phases on the timestamp from the status and only look at the last status from there
Ad 1: it looks now like this:
ID NAME PHASE
1 John C
2 Jane C
3 Tom C
4 Pete C
5 Anna C
1 John D
2 Jane D
3 Tom D
And obviously I want this:
ID NAME PHASE
4 Pete C
5 Anna C
1 John D
2 Jane D
3 Tom D
I now I cannot use GROUP BY here because I then have to use a COUNT or similar like grouping functions.
Is there any SQL guru here to help me out?
1 Answer