【问题标题】:Count units by active and inactive dates按活动和非活动日期计算单位
【发布时间】:2020-08-19 23:42:16
【问题描述】:

我有一个结构如下的表

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


    【解决方案1】:

    生成一系列日期,将其加入表格并计算每个日期的单位:

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

    【讨论】:

    • 完美,非常感谢!我实际上也有一个 calendardates 表,我只是在您的代码中替换了它以获得相同的结果
    • 当然可以,虽然日历表基本上是多余的。
    【解决方案2】:

    就像库存查询一样。

    建立一个中间两列表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;
    

    【讨论】:

    • 当我运行它我得到错误:聚合窗口函数与 ORDER BY 子句需要一个框架子句
    【解决方案3】:

    一个选项是取消透视行,然后聚合:

    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
    

    【讨论】:

    • 当我运行它时,我得到了错误:t 中不存在列“date_active”
    【解决方案4】:

    这是一个完全类似的场景 - 只是它是时间戳而不是基于日期...针对 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 2017-11-26
      • 2018-12-05
      相关资源
      最近更新 更多