sql - SQL子查询的替代方式是什么?
问题描述
我需要在第一个约会日期显示所有患者的信息。在这里,我附上了我所需信息的图像。请看一看:
我解决了它,但我想更有效地做到这一点。这是我的解决方案:
SELECT ROW_NUMBER() OVER(ORDER BY p.Name) SINo,
or1.PatientID RegNo,
p.Name PatientName,
or1.DataHead Diagnosis,
or1.AppointmentDate,
'First Appointment Date' = (
SELECT or2.AppointmentDate
FROM OPDConsultancyRepository AS or2
WHERE or2.OPDConsultancyRepositoryID = (
(
SELECT MIN(or3.OPDConsultancyRepositoryID)
FROM OPDConsultancyRepository AS or3
WHERE or3.DataType = 3
AND or3.DoctorID = 2139 AND or3.PatientID=or1.PatientID
GROUP BY
or3.PatientID
)
)
)
FROM OPDConsultancyRepository AS or1
INNER JOIN Patient AS p
ON p.PatientID = or1.PatientID
WHERE or1.DataType = 3
AND or1.DoctorID = 2139
ORDER BY
p.Name
执行计划:
Above query needs 6 sec to produce output.
那么有什么建议我如何优化它?
解决方案
如果没有 DDL 和执行计划,就不可能确切地说出是什么让你慢了下来。肯定会减慢您速度的一件事是相关子查询。请注意这篇文章:隐藏的 RBAR:Triangular Joins Second - 失去那个ORDER BY p.name
你不需要的决赛。如果必须为显示目的对输出进行排序,则让应用程序处理它。最后,您应该检查最昂贵的执行计划并在需要的地方添加索引。
我将构建此查询的方式是首先将其设置为您拥有所有列的点,包括所有相关的患者ID 和约会日期记录。
DECLARE @table TABLE (patientId INT, appointmentDate DATE);
INSERT @table VALUES (1,GETDATE()),(1,GETDATE()-3),(2,GETDATE()-10),(2,GETDATE()-20),
(3,GETDATE()-30),(4,GETDATE()-3),(4,GETDATE()),(4,GETDATE()-100);
SELECT t.patientId, t.appointmentDate FROM @table AS t;
您可以将逻辑转换为索引视图,其中 UNIQUE CLUSTERED INDEX 位于 PatientID 和 AppointmentDate 上。然后将该查询转换为子查询,您有几个选择:
DECLARE @table TABLE (patientId INT, appointmentDate DATE);
INSERT @table VALUES (1,GETDATE()),(1,GETDATE()-3),(2,GETDATE()-10),(2,GETDATE()-20),
(3,GETDATE()-30),(4,GETDATE()-3),(4,GETDATE()),(4,GETDATE()-100);
-- Option #1 -- GROUP BY + MIN
SELECT t.patientId, MIN(t.appointmentDate)
FROM @table AS t
GROUP BY t.patientId;
-- Option #2 -- Partitioned ROW_NUMBER() filtered for WHERE rn=1 in subquery
SELECT
d.patientId,
d.appointmentDate
FROM
(
SELECT
t.patientId,
t.appointmentDate,
rn = ROW_NUMBER() OVER (PARTITION BY t.patientId ORDER BY appointmentDate)
FROM @table AS t
) AS d
WHERE d.rn = 1;
-- Option #3 -- TOP (1) WITH TIES + ROW_NUMBER()
SELECT TOP (1) WITH TIES t.*
FROM @table AS t
ORDER BY ROW_NUMBER() OVER (PARTITION BY t.patientId ORDER BY appointmentDate);
推荐阅读
- flutter - 如果用户登录正确颤动,如何从表中选择所有数据
- python - 从字符串确定日期时间格式
- php - 不要在 WooCommerce 中对缺货产品应用优惠券折扣
- mathjax - `
` 不适用于资源管理器可访问性 - python - BS4 replace_with 结果不再在树中
- javascript - React 道具对我不起作用 我正在设计一张卡片
- python - Python - Mailosaur 获取 HTML 元素
- laravel - 如何在编译后的视图文件中执行 javascript(使用 View::render 方法)
- javascript - 如何从超级代理响应中提取 cookie?
- javascript - npm:在上下文中执行?