1

私にとってシナリオを説明するのは難しいですが、解雇会議の準備ができているユーザー(実際には「患者」)のリストを取得したいと思います。

状況

私は患者テーブルを持っています:

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)

私の質問

私は今、本当に思いつかないクエリを探しています。私の論理は次のとおりです。

  1. すべての患者を選択します。
  2. 最後のステータス(タイムスタンプに基づく)がフェーズ名「C」または「D」からのものである場合。
  3. タイプ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つあります。

  1. 私は患者をリストの2倍にしています。フェーズDの患者は、フェーズCの患者としても発生します(したがって2倍)。試しましたSELECT DISTINCTがうまくいきませんでした
  2. 名前に基づいてフェーズを除外しますが、タイムスタンプのフェーズをステータスから並べ替えて、そこから最後のステータスのみを確認したいと思います。

広告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の第一人者はいますか?

4

1 に答える 1

0
SELECT p.id, p.name, max(ph.name) as phase

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 (m.type != 'meeting_planned' OR m.type IS NULL)
    AND p.id not in (
        select p.id
        from 
            patient p
            inner join
            status s on p.id = s.patient_id
            inner join
            phase ph on ph.id = s.phase_id
        where ph.name > 'D'
        ) s
group by p.id, p.name
于 2012-10-09T14:20:17.013 に答える