单个SQL查询中带有条件的最小和最大

时间:2019-07-19 10:54:01

标签: sql postgresql

我有一张类似的桌子

create table appointments
(
    id                  serial   not null constraint appointments_pkey           primary key,
    patient_id          varchar(255)                                   not null,
    date                timestamp(0)  not null 
);

我想在单个查询中获取下一个约会和上一个约会的日期。

我创建的查询方式为

 SELECT
        (
                    SELECT MIN(ap.date) FROM appointments ap
                    WHERE ap.date >= NOW() AND ap.patient_id = '1'
        ) AS next,
        (
                    SELECT MAX(ap.date) FROM appointments ap
                    WHERE ap.date < NOW() AND ap.patient_id = '1'
        ) AS last

可以按预期工作,但是我认为由于两个子查询,它没有得到优化。 请您帮我优化这样的查询吗?

2 个答案:

答案 0 :(得分:2)

您可以使用case when expression

select 
    min(case when ap.date >= NOW() then ap.date end) next,
    max(case when ap.date < NOW() then ap.date end) last
from appointments ap
where ap.patient_id = '1'

答案 1 :(得分:0)

您的方法可能很好。我更可能使用union all来实现此目的,

(SELECT ap.*
 FROM appointments ap
 WHERE ap.patient_id = 1 AND ap.date >= NOW()
 ORDER BY ap.date DESC
 FETCH FIRST 1 ROW ONLY
) UNION ALL
(SELECT ap.*
 FROM appointments ap
 WHERE ap.patient_id = 1 AND ap.date < NOW()
 ORDER BY ap.date ASC
 FETCH FIRST 1 ROW ONLY
) ;

这将返回整个行,而不仅仅是日期。

通过该查询,您都可以利用appointments(patient_id, date)上的索引。其他解决方案(例如条件聚合和窗口函数)可能不会利用索引,因此需要扫描整个表。