如何实现条件数组聚合?

Sai*_*ifi 2 sql arrays postgresql

为简单起见,我将使用以下内容patientappointment表格。


CREATE TABLE patient
    (id int primary key, name text);


INSERT INTO patient
    (id, name)
VALUES
    (1, 'Jane'),
    (2, 'John');

CREATE TABLE appointment
    (patient_id int, status text, scheduled_time timestamp);

INSERT INTO appointment
    (patient_id, status, scheduled_time)
VALUES
    (1, 'completed', '2019-04-09 10:00:00'),
    (2, 'active',    '2022-10-01 11:30:00'),
    (2, 'canceled',  '2021-10-01 09:30:00');

Run Code Online (Sandbox Code Playgroud)

我想要的是一份包含以下数据的报告。

Patient Name, All Appointment States, Future Active Appointments    
Run Code Online (Sandbox Code Playgroud)

所以我需要做的是:

  1. 从患者表中获取患者姓名
  2. 汇总患者的所有预约状态
  3. 聚合状态='活动'的约会的所有约会时间

所以我创建的初始查询是:

Patient Name, All Appointment States, Future Active Appointments    
Run Code Online (Sandbox Code Playgroud)

数据库小提琴

然而,上述满足了前两个要求,但是对于第三个要求,它聚合了所有计划时间,而不仅仅是那些具有活动状态的时间。

array_agg(field WHERE )如果能像下面这样工作那就太好了:

SELECT p.name AS "Patient Name", 
array_agg(a.status) AS "All Appointment States", 
array_agg(a.scheduled_time) AS "Future Active Appointments"        
FROM patient p
LEFT JOIN appointment a ON a.patient_id = p.id
GROUP BY p.id;
Run Code Online (Sandbox Code Playgroud)

但上面的方法不起作用。那么还有另一种简单的方法可以实现这一目标吗?

小智 6

您正在寻找以下filter()选项:

SELECT p.name AS "Patient Name", 
       array_agg(a.status) AS "All Appointment States", 
       array_agg(a.scheduled_time) filter (WHERE a.status='active') AS "Future Active Appointments"        
FROM patient p
  LEFT JOIN appointment a ON a.patient_id = p.id
GROUP BY p.id;
Run Code Online (Sandbox Code Playgroud)