私にとってシナリオを説明するのは難しいですが、解雇会議の準備ができているユーザー(実際には「患者」)のリストを取得したいと思います。
状況
私は患者テーブルを持っています:
PATIENT
id (int)
name (varchar)
患者は、私がフェーズを定義した特別なプロセスに従います。
PHASE
id (int)
name (varchar)
そして、私は患者のすべての段階を記録します:
STATUS
id (int)
phase_id (int)
patient_id (int)
timestamp (datetime)
「会議の準備ができている」という用語は、会議が計画されていることを意味します。このような計画された会議は、メッセージテーブルに記録されます。計画された会議のメッセージのタイプは「meeting_planned」であり、たとえば、会議が完了すると、新しいメッセージ「meeting_done」があります。
MESSAGE
id (int)
patient_id (int)
type (enum)
value (varchar)
timestamp (datetime)
私の質問
私は今、本当に思いつかないクエリを探しています。私の論理は次のとおりです。
- すべての患者を選択します。
- 最後のステータス(タイムスタンプに基づく)がフェーズ名「C」または「D」からのものである場合。
- タイプmeeting_plannedのメッセージがない場合。
広告2:患者は2つのフェーズのいずれかになります。患者がフェーズA、B、E、またはFにある場合、会議を計画することはできません。看護師は、患者がフェーズCにあるときにすでに会議を計画することを決定できますが、それが行われなかった場合は、フェーズDで行われます(Dは常にCに続き、A> B> C> D> E> Fです)。
広告3:他のメッセージがあるかもしれませんが、このタイプでは決してありません。type+patient_idには固有の制約があります。会議が計画されて行われた場合、2つのメッセージがあります(タイプ1 = Meeting_planned、タイプ2 = Meeting_done)。会議が計画されていない場合、タイプmeeting_plannedは発生しませんが、他のメッセージがすでに設定されている可能性があります。
私が試したこと
私は今このクエリを思いついた:
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)
私の質問
上記のクエリでは、管理できないことが2つあります。
- 私は患者をリストの2倍にしています。フェーズDの患者は、フェーズCの患者としても発生します(したがって2倍)。試しました
SELECT DISTINCT
がうまくいきませんでした - 名前に基づいてフェーズを除外しますが、タイムスタンプのフェーズをステータスから並べ替えて、そこから最後のステータスのみを確認したいと思います。
広告1:次のようになりました:
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
そして明らかに私はこれが欲しい:
ID NAME PHASE
4 Pete C
5 Anna C
1 John D
2 Jane D
3 Tom D
グループ化関数などGROUP BY
を使用する必要があるため、ここでは使用できません。COUNT
私を助けるためにここにSQLの第一人者はいますか?