MySQL是否有一种方法可以选择按列分组的前N条记录

时间:2019-10-30 13:32:44

标签: mysql sql

所以我对MySQL还是很陌生,所以如果这是一个愚蠢的问题,我表示歉意,但是还是简单起见,我可以说我有2个表:耐心和约会。我想获得给定数量的患者(在此示例中为50个),并使用给定的过滤器进行所有约会。

现在我正在执行以下操作,但速度很慢:

SELECT
   t2.* 
FROM
   (
      SELECT
         patient_id 
      FROM
         patient 
         LEFT JOIN
            appointment 
            ON appointment.patient_id = patient.patient_id  
    /* a bunch of filters and other joins */
      GROUP BY
         patient_id LIMIT 50 
   )
   t1 
   LEFT JOIN
      (
         SELECT
            patient_id 
         FROM
            patient 
            LEFT JOIN
               appointment 
               ON appointment.patient_id = patient.patient_id   
        /* a bunch of filters and other joins */
      )
      t2 
      ON t1.patient_id = t2.patient_id

我想知道是否有更好的方法可以做到这一点。感觉就像我在做额外的工作,因为我基本上在t1和t2中做同样的事情,只是对t1进行分组。是否可以通过前50个不同的Patient_id摆脱t1和LIMIT t2?有什么想法吗?谢谢!

3 个答案:

答案 0 :(得分:1)

您的代码似乎正在根据patientId的值选择前50名患者。这使用的GROUP BY隐式顺序已弃用。您应该在ORDER BY之前有一个明确的LIMIT

您可以通过消除使用rank()来简化查询:

SELECT t.* 
FROM (SELECT . . ,
             DENSE_RANK() OVER (ORDER BY p.Patient_Id) as seqnum
      FROM patient p LEFT JOIN
           appointment a
           ON a.patient_id = p.patient_id  
    /* a bunch of filters and other joins */
      GROUP BY p.patient_id
     ) t 
WHERE seqnum <= 50;

编辑:

在旧版本中,可以使用变量来达到相同的效果:

SELECT t.*
FROM (SELECT t.*,
             (@rn := if(@p = patient_id, @rn + 1,
                        if(@p := patient_id, 1, 1)
                       )
             ) as seqnum
      FROM (SELECT . . 
            FROM patient p LEFT JOIN
                 appointment a
                 ON a.patient_id = p.patient_id  
          /* a bunch of filters and other joins */
            GROUP BY p.patient_id
            ORDER BY p.patient_id
           ) t CROSS JOIN
           (SELECT @p := '', @rn := 0) params
     ) t
WHERE seqnum <= 50;

答案 1 :(得分:0)

您可以使用子查询来查找前50名患者。然后,一个简单的LEFT JOIN就可以做到:

select
  p.*, a.*
from patient p
left join appointment a on a.patient_id = p.patient_id
where p.patient_id in (
    select patient_id from patient order by patient_id limit 50
  )
  and p.registration_date > '2019-01-01' -- example of extra filtering condition

请记住,如果要使用约会列放置过滤条件,则需要将其放置在ON子句中,而不是WHERE子句中;否则它将[最有可能]击败LEFT JOIN

答案 2 :(得分:-1)

可以通过以下方式简化查询。

因为基本要求是要获得50位患者的病历以及约会详细信息。

在这种情况下,等值连接会有所帮助。

等值联接仅返回指定列具有相等值的行。

3