按活动和非活动日期计算单位

问题描述 投票:0回答:4

我有一个具有以下结构的表

table
unit      date_active  date_inactive
a         2018-01-01   NULL
b         2018-01-01   2020-07-05
c         2019-02-01   2020-01-01

我需要一个查询来生成从首次活动日期到今天的按月活动单位总数。输出需要遵循以下内容:

2018-01-01 2
2018-02-01 2
....

当日期不活动为 NULL 时,该单位今天仍然处于活动状态。我正在使用 PostgreSQL

sql postgresql aggregate-functions
4个回答
3
投票

生成一系列日期,将其连接到表中并计算每个日期的单位:

select m::date as month, count(unit)
from generate_series('2018-01-01'::date, '2020-12-31', '1 month') m
left join my_table on m::date between date_active and coalesce(date_inactive, 'infinity')
group by 1
order by 1

Db<>小提琴。


0
投票

就像库存查询一样。

建立一个中间两列表

counters
,以开始日期和+1作为计数器,UNION ALL结束日期和-1作为计数器。

在该中间表上运行计数器的运行总和。

WITH
counters(dt,counter) AS (
  SELECT
    date_active
  , 1
  FROM input
  UNION ALL
  SELECT
    date_inactive 
  , -1
  FROM input
)
SELECT
  dt
, SUM(counter) OVER(ORDER BY ts) AS active_count
FROM counters;

0
投票

一个选项对行进行逆透视,然后聚合:

select x.dt, sum(sum(x.cnt)) over(order by x.dt) cnt
from mytable t
cross join lateral (values
    (date_active, 1),
    (date_inactive, -1)
) x(dt, cnt)
where x.dt is not null
group by x.dt
order by x.dt

0
投票

这是一个完全类似的场景 - 只是它是时间戳而不是基于日期...针对 PostgreSQL 12.4 运行它。

WITH
input(unit,ts_active,ts_inactive) AS (
          SELECT 'w',TIMESTAMP '2020-08-13 00:58:14.528778',TIMESTAMP '2020-08-13 00:58:14.552428'
UNION ALL SELECT 'w',TIMESTAMP '2020-08-13 00:59:32.022632',TIMESTAMP '2020-08-13 00:59:32.042015'
UNION ALL SELECT 'w',TIMESTAMP '2020-08-13 01:20:31.555526',TIMESTAMP '2020-08-13 01:20:31.599932'
UNION ALL SELECT 'w',TIMESTAMP '2020-08-13 01:23:55.585023',TIMESTAMP '2020-08-13 01:23:55.655960'
UNION ALL SELECT 'c',TIMESTAMP '2020-08-13 16:09:40.286047',TIMESTAMP '2020-08-13 16:09:40.332600'
UNION ALL SELECT 'c',TIMESTAMP '2020-08-13 16:09:51.887808',TIMESTAMP '2020-08-13 16:09:51.913150'
UNION ALL SELECT 'c',TIMESTAMP '2020-08-13 16:09:51.919182',TIMESTAMP '2020-08-13 16:09:52.023836'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:11.904413',TIMESTAMP '2020-08-13 16:11:11.921197'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:25.617580',TIMESTAMP '2020-08-13 16:11:26.084465'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:25.624842',TIMESTAMP '2020-08-13 16:11:25.631024'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:25.640343',TIMESTAMP '2020-08-13 16:11:25.647049'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:25.655991',TIMESTAMP '2020-08-13 16:11:25.662542'
UNION ALL SELECT 'i',TIMESTAMP '2020-08-13 16:11:25.691300',TIMESTAMP '2020-08-13 16:11:25.934098'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:25.958651',TIMESTAMP '2020-08-13 16:11:26.032297'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:11:26.076818',TIMESTAMP '2020-08-13 16:11:26.083056'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:23:23.779083',TIMESTAMP '2020-08-13 16:23:23.812426'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 16:23:34.150468',TIMESTAMP '2020-08-13 16:23:34.176461'
UNION ALL SELECT 't',TIMESTAMP '2020-08-13 17:30:16.483214',TIMESTAMP '2020-08-13 17:30:16.490638'
UNION ALL SELECT 'c',TIMESTAMP '2020-08-13 17:30:16.492756',TIMESTAMP '2020-08-13 17:30:16.505191'
UNION ALL SELECT 's',TIMESTAMP '2020-08-13 17:30:29.819721',TIMESTAMP '2020-08-13 17:30:29.957229'
)
,
counters(ts,counter) AS (
  SELECT
    ts_active
  , 1
  FROM input
  UNION ALL
  SELECT
    ts_inactive 
  , -1
  FROM input
)
SELECT
  ts
, SUM(counter) OVER(ORDER BY ts) AS active_count
FROM counters;
             ts             | active_count 
----------------------------+--------------
 2020-08-13 00:58:14.528778 |            1
 2020-08-13 00:58:14.552428 |            0
 2020-08-13 00:59:32.022632 |            1
 2020-08-13 00:59:32.042015 |            0
 2020-08-13 01:20:31.555526 |            1
 2020-08-13 01:20:31.599932 |            0
 2020-08-13 01:23:55.585023 |            1
 2020-08-13 01:23:55.65596  |            0
 2020-08-13 16:09:40.286047 |            1
 2020-08-13 16:09:40.3326   |            0
 2020-08-13 16:09:51.887808 |            1
 2020-08-13 16:09:51.91315  |            0
 2020-08-13 16:09:51.919182 |            1
 2020-08-13 16:09:52.023836 |            0
 2020-08-13 16:11:11.904413 |            1
 2020-08-13 16:11:11.921197 |            0
 2020-08-13 16:11:25.61758  |            1
 2020-08-13 16:11:25.624842 |            2
 2020-08-13 16:11:25.631024 |            1
 2020-08-13 16:11:25.640343 |            2
 2020-08-13 16:11:25.647049 |            1
 2020-08-13 16:11:25.655991 |            2
 2020-08-13 16:11:25.662542 |            1
 2020-08-13 16:11:25.6913   |            2
 2020-08-13 16:11:25.934098 |            1
 2020-08-13 16:11:25.958651 |            2
 2020-08-13 16:11:26.032297 |            1
 2020-08-13 16:11:26.076818 |            2
 2020-08-13 16:11:26.083056 |            1
 2020-08-13 16:11:26.084465 |            0
 2020-08-13 16:23:23.779083 |            1
 2020-08-13 16:23:23.812426 |            0
 2020-08-13 16:23:34.150468 |            1
 2020-08-13 16:23:34.176461 |            0
 2020-08-13 17:30:16.483214 |            1
 2020-08-13 17:30:16.490638 |            0
 2020-08-13 17:30:16.492756 |            1
 2020-08-13 17:30:16.505191 |            0
 2020-08-13 17:30:29.819721 |            1
 2020-08-13 17:30:29.957229 |            0
© www.soinside.com 2019 - 2024. All rights reserved.