generate_series用于创建月份列表以获取缺少的日期

时间:2018-02-20 15:24:47

标签: sql postgresql

我有一个每月出勤的视图(日期按月截断):

----------------------------------------------------
| Student_ID    | Date             | Attendance    |
----------------------------------------------------
| 1             | 2017-01-01       | 4             |
| 1             | 2017-02-01       | 3             |
| 1             | 2017-04-01       | 4             |
| 1             | 2017-06-01       | 2             |
| 2             | 2017-03-01       | 5             |
| 2             | 2017-05-01       | 2             |
----------------------------------------------------

正如您所看到的,并非每个月都会显示每个ID,因为此视图会对实际考勤表中显示的每个日期进行计数和分组。尽管如此,我每个月都需要显示每个ID,即使是0。

----------------------------------------------------
| Student_ID    | Date             | Attendance    |
----------------------------------------------------
| 1             | 2017-01-01       | 4             |
| 1             | 2017-02-01       | 3             |
| 1             | 2017-03-01       | 0             |
| 1             | 2017-04-01       | 4             |
| 1             | 2017-05-01       | 0             |
| 1             | 2017-06-01       | 2             |
| 2             | 2017-01-01       | 0             |
| 2             | 2017-02-01       | 0             |
| 2             | 2017-03-01       | 5             |
| 1             | 2017-04-01       | 0             |
| 2             | 2017-05-01       | 2             |
| 1             | 2017-06-01       | 0             |
----------------------------------------------------

我尝试不成功地调用此视图并使用

进行完全连接
SELECT
    CAST(CAST('2017-01-01' AS DATE) + (interval '1' month * generate_series(0,11)) AS DATE) AS month,
    0 AS attendance

但它不起作用,但我觉得有点接近实际的解决方案。帮助赞赏。

1 个答案:

答案 0 :(得分:3)

使用cross join生成每个student_id的所有日期组合,然后在其上left join生成原始表格,以获取包含0值的缺失行。

select i.student_id,m.mth,coalesce(t.attendance,0)
from (select distinct student_id from tbl) i
cross join generate_series('2017-01-01'::date,'2017-12-01'::date, '1 MONTH') m(mth)
left join tbl t on t.student_id=i.student_id and t.dt=m.mth