简体   繁体   English

PostgreSQL 每天每个状态的计数

[英]PostgreSQL count of each status per day

I have the following table:我有下表:

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 |

I also have a table with every calendar day from 2019-11-01 to 2019-12-31.从 2019 年 11 月 1 日到 2019 年 12 月 31 日,每个日历日我都有一张桌子。

I need to find out how many occurrences of each status exist per calendar day for the time span listed above.我需要找出在上面列出的时间跨度内每个日历日存在的每种状态的出现次数。

If a status is Opened on 2019-12-14 and Pending on 2019-12-17, I need to count that it was Opened for every day from 2019-12-14 to 2019-12-17.如果状态是在2019年12月14日和待定的2019年12月17日开业,我需要计算,它被打开每天从2019年12月14日至2019年12月17日。

Ideal:理想的:

|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 |

Any help is greatly appreciated.任何帮助是极大的赞赏。

Edit: The solution from GMB below is very close, but it leaves me with the following table:编辑:下面来自 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 |                     |

How do I add the end date to my range (2019-12-31) to the missing column values?如何将结束日期添加到我的范围 (2019-12-31) 到缺失的列值?

I would do it this way: Get the start and end of each status per id, count occurence using your table with every calendar day from 2019-11-01 to 2019-12-31 and do a basic count by status and date我会这样做:获取每个 ID 的每个状态的开始和结束,使用您的表计算从 2019-11-01 到 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

Consider the following query:考虑以下查询:

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

This works by cross-joining the calendar table with the list of distinct status available in the table, and then joining it with a subquery that uses lead() to get the date of the next status associated to each record.这是通过将日历表与表中可用的不同状态列表交叉连接,然后将其与使用lead()的子查询连接来获得与每条记录关联的下一个状态的日期来实现的。 If you have a table of statuses, you can use it instead of the subquery that selects the distinct statuses.如果您有状态表,则可以使用它代替选择不同状态的子查询。

Demo on DB Fiddle : DB Fiddle 上的演示

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

Note that the DB Fiddle demonstrates how to use handy Postgres function generate_series() to fill in the calendar table.请注意,DB Fiddle 演示了如何使用方便的 Postgres 函数generate_series()来填充日历表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM