【问题标题】:PostgreSQL count of each status per day每天每个状态的 PostgreSQL 计数
【发布时间】:2020-01-21 15:04:34
【问题描述】:

我有下表:

Reservations
| id | status    | created_at          |
|  1 | Opened    | 2019-11-12 11:46:11 |
|  1 | Completed | 2019-11-19 23:03:24 |
|  1 | Pending   | 2019-11-15 12:04:13 |
|  2 | Opened    | 2019-11-14 11:46:11 |
|  2 | Completed | 2019-11-20 23:03:24 |
|  2 | Pending   | 2019-11-17 12:04:13 |

我还有一张表,从 2019 年 11 月 1 日到 2019 年 12 月 31 日的每个日历日。

我需要找出在上面列出的时间跨度内每个日历日每个状态出现的次数。

如果状态是 Opened 于 2019-12-14 和 Pending 在 2019-12-17,我需要计算它是 Openedem> 从 2019-12-14 到 2019-12-17 的每一天。

理想:

|2019-11-12 00:00:00 | Opened    | 1 |
|2019-11-12 00:00:00 | Pending   | 0 |
|2019-11-12 00:00:00 | Completed | 0 |
|2019-11-13 00:00:00 | Opened    | 1 |
|2019-11-13 00:00:00 | Pending   | 0 |
|2019-11-13 00:00:00 | Completed | 0 |
|2019-11-14 00:00:00 | Opened    | 2 |
|2019-11-14 00:00:00 | Pending   | 0 |
|2019-11-14 00:00:00 | Completed | 0 |
|2019-11-15 00:00:00 | Opened    | 1 |
|2019-11-15 00:00:00 | Pending   | 1 |
|2019-11-15 00:00:00 | Completed | 0 |

非常感谢任何帮助。

编辑: 下面 GMB 的解决方案非常接近,但它给我留下了下表:

| status    | created_at          | ended_at            |
| Opened    | 2019-11-12 11:46:11 | 2019-11-15 12:04:13 |
| Pending   | 2019-11-15 12:04:13 | 2019-11-19 23:03:24 |
| Completed | 2019-11-19 23:03:24 |                     |
| Opened    | 2019-11-14 11:46:11 | 2019-11-17 12:04:13 |
| Pending   | 2019-11-17 12:04:13 | 2019-11-20 23:03:24 |
| Completed | 2019-11-20 23:03:24 |                     |

如何将结束日期添加到我的范围 (2019-12-31) 到缺少的列值?

【问题讨论】:

    标签: sql postgresql date calendar


    【解决方案1】:

    考虑以下查询:

    select 
        c.dt,
        s.status,
        count(t.status)
    from 
        calendar c
        cross join (select distinct status from reservations) s
        left join (
            select 
                status, 
                created_at, 
                lead(created_at) over(partition by id order by created_at) ended_at
            from reservations
        ) t
            on  t.status = s.status
            and c.dt  + interval '1 day' >= t.created_at
            and c.dt + interval '1 day' < t.ended_at
    group by c.dt, s.status
    order by c.dt, s.status
    

    这通过将日历表与表中可用的不同状态列表交叉连接,然后将其与使用lead() 的子查询连接以获取下一个状态的日期关联到每条记录。如果您有一个状态表,则可以使用它来代替选择不同状态的子查询。

    Demo on DB Fiddle

    dt |状态 |数数 :--------------------- | :-------- | ----: 2019-11-12 00:00:00+00 |已完成 | 0 2019-11-12 00:00:00+00 |已打开 | 1 2019-11-12 00:00:00+00 |待定 | 0 2019-11-13 00:00:00+00 |已完成 | 0 2019-11-13 00:00:00+00 |已打开 | 1 2019-11-13 00:00:00+00 |待定 | 0 2019-11-14 00:00:00+00 |已完成 | 0 2019-11-14 00:00:00+00 |已打开 | 2 2019-11-14 00:00:00+00 |待定 | 0 2019-11-15 00:00:00+00 |已完成 | 0 2019-11-15 00:00:00+00 |已打开 | 1 2019-11-15 00:00:00+00 |待定 | 1

    请注意,DB Fiddle 演示了如何使用方便的 Postgres 函数 generate_series() 来填写日历表。

    【讨论】:

      【解决方案2】:

      我会这样做: 获取每个 id 的每个状态的开始和结束,在 2019 年 11 月 1 日至 2019 年 12 月 31 日的每个日历日使用您的表格计算出现次数,并按状态和日期进行基本计数

      with Reservations cte as 
      (
       select 
       a.id, a.status, a.created_at::date, 
       LAG(a.created_at::date, 1,0) OVER (PARTITION BY YEAR(a.id) ORDER BY YEAR(a.created_at)) 
       AS Ended_at
       Reservations a 
      )
      Select b.day, status, count(*)  
      from Reservations a inner join calendar b on b.day >= created_at and
      b.day < Ended_at       
      group by b.day, status
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-01-08
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 2019-04-12
        • 2021-10-06
        • 1970-01-01
        相关资源
        最近更新 更多