根据记录的条目查找用户列表

时间:2012-10-09 13:42:34

标签: mysql distinct

对我而言,这个场景很难解释,但我希望获得一份准备参加解雇会的用户名单(实际上是“病人”)。

情况

我有一张病人桌:

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。
  4. Ad 2:患者可以处于两个阶段中的一个阶段。当患者处于A,B,E或F期时,则无法计划会议。当患者处于阶段C时,护士可以决定计划会议,但是如果没有发生,则将在阶段D发生(D总是在C之后,A> B> C> D> E> F>。

    广告3:可能还有其他消息,但从不使用此类型。类型+ patient_id上有一个独特的constaint。如果已经计划并且已经发生了会议,则会有两条消息(类型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)
    

    我的问题

    在上面的查询中,我有两件事我无法管理:

    1. 我的病人名单中有两倍。 D期的任何患者也在C期作为患者出现(因此加倍)。我尝试了一个SELECT DISTINCT,但没有成功
    2. 我现在根据他们的名字排除阶段,但我想从状态订购时间戳的阶段,只查看那里的最后状态
    3. 广告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大师来帮助我?

1 个答案:

答案 0 :(得分: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
相关问题