所以我对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?有什么想法吗?谢谢!
答案 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