GROUP BY外键和日期范围

时间:2018-12-14 12:56:30

标签: sql postgresql

我正在使用名为appointments的表,这些列是:

scheduled_at:日期时间 doctor_id:整数 说明:文字 finish_at:datetime

我想获得按doctor_id分组以及按一组日期间隔分组的所有约会的计数,这些日期间隔根据给定的输入集而变化。我得到的输入是:from是日期,to是日期。

我要解决的第一个用例是将给定的fromto中的结果按月划分。因此,如果给我from ='2018-02-03'和to ='2018-10-03',我想获取为每个医生完成的所有约会的COUNT,并且从2018-022018-10的每个月。

我知道如何按Doctor_id进行分组,但是我不知道如何对这些动态日期间隔进行分组。

这是我到目前为止所拥有的:

SELECT COUNT(*) FROM appointments WHERE finished_at IS NOT NULL GROUP BY doctor_id

我知道,如果事先有间隔,我可以进行尽可能多的查询,因此最终我每个月都要进行一次查询,例如:

SELECT COUNT(*) FROM appointments WHERE finished_at IS NOT NULL AND scheduled_at BETWEEN '2018-02-01' AND '2018-03-01' GROUP BY doctor_id

SELECT COUNT(*) FROM appointments WHERE finished_at IS NOT NULL AND scheduled_at BETWEEN '2018-03-01' AND '2018-04-01' GROUP BY doctor_id

我只是想知道是否有一种方法可以在SQL中做到这一点,所以我只需要执行一个查询。

3 个答案:

答案 0 :(得分:1)

您可以使用条件聚合:

SELECT doctor_id,
       SUM(CASE WHEN scheduled_at BETWEEN '2018-02-01' AND '2018-03-01' THEN 1 ELSE 0 END),
       SUM(CASE WHEN scheduled_at BETWEEN '2018-03-01' AND '2018-04-01' THEN 1 ELSE 0 END)    
FROM appointments
WHERE finished_at IS NOT NULL
GROUP BY doctor_id

答案 1 :(得分:1)

使用case表达式进行条件聚合

SELECT doctor_id,
       COUNT(*),
       COUNT(case when scheduled_at BETWEEN '2018-02-01' AND '2018-03-01' then 1 end),
       COUNT(case when scheduled_at BETWEEN '2018-03-01' AND '2018-04-01' then 1 end)
FROM appointments
WHERE finished_at IS NOT NULL
GROUP BY doctor_id

或者也有group by年和月的查询:

SELECT doctor_id, year(scheduled_at), month(scheduled_at), COUNT(*)
FROM appointments
WHERE finished_at IS NOT NULL
GROUP BY doctor_id, year(scheduled_at), month(scheduled_at)

或者,也许应该使用ANSI SQL函数EXTRACT

SELECT doctor_id,
       extract(year from scheduled_at), extract(month from scheduled_at), COUNT(*)
FROM appointments
WHERE finished_at IS NOT NULL
GROUP BY doctor_id, extract(year from scheduled_at), extract(month from scheduled_at)

答案 2 :(得分:0)

如果您的postgres版本是9.4或更高版本,则应考虑使用FILTER谓词,它比case语句更易读,性能更高。

SELECT doctor_id,
       COUNT(*) AS total,
       COUNT(*) FILTER (WHERE scheduled_at BETWEEN '2018-02-01' AND '2018-03-01') AS date_feb,
       COUNT(*) FILTER (WHERE scheduled_at BETWEEN '2018-03-01' AND '2018-04-01') AS date_mar
FROM appointments
WHERE finished_at IS NOT NULL
GROUP BY doctor_id