【问题标题】:PostgreSQL: Count items created before a time range in a seriesPostgreSQL:计算在一系列时间范围之前创建的项目
【发布时间】:2014-11-12 09:59:52
【问题描述】:

说明

考虑PostgreSQL 9.3 数据库中的下表:

                                        Table "public.users"
       Column       |           Type           |                      Modifiers
--------------------+--------------------------+-----------------------------------------------------
 sid                | bigint                   | not null default nextval('users_sid_seq'::regclass)
 creation_time      | timestamp with time zone | default now()
 ...

我想生成一个时间戳之前创建的用户数量的报告,针对一系列时间戳,应该如下所示:

    sampling_time    |   number_of_users |
---------------------+-------------------+
 2014-11-01 00:00:00 |   100             |
 2014-11-02 00:00:00 |   105             |
 2014-11-03 00:00:00 |   110             |
 2014-11-04 00:00:00 |   120             |
 2014-11-05 00:00:00 |   125             |
 2014-11-06 00:00:00 |   150             |
 2014-11-07 00:00:00 |   201             |
 2014-11-08 00:00:00 |   100             |
 2014-11-09 00:00:00 |   250             |
 2014-11-10 00:00:00 |   300             |
 2014-11-11 00:00:00 |   400             |

我尝试过的

使用generate_series 可以轻松生成时间戳系列:

SELECT generate_series('2014-11-01'::timestamp, 
                       '2014-11-11'::timestamp, 
                       '1 day'::interval) AS sampling_time

查询

尝试将系列和用户上的COUNT(*) 组合失败:

SELECT * FROM

(SELECT generate_series('2014-11-01'::timestamp, 
                        '2014-11-11'::timestamp, 
                        '1 day'::interval)) AS sampling_time,

(SELECT COUNT(*) 
        FROM users 
        WHERE creation_time<=sampling_time) 
AS created_before_sampling_time;

错误信息

ERROR:  column "sampling_time" does not exist
LINE 7:             WHERE creation_time<=sampling_time) 

知道如何根据每行的samping_time 子查询用户计数吗?

【问题讨论】:

    标签: sql postgresql subquery date-range


    【解决方案1】:

    尝试改用window function

    SELECT
      sampling_time.date,
      SUM(COUNT(u.*)) OVER (ORDER BY sampling_time.date) AS number_of_users
    FROM
      GENERATE_SERIES(
        (SELECT MIN(creation_time::date) FROM users),
        CURRENT_DATE,
        '1 day'::interval
      ) sampling_time LEFT JOIN users
    ON
      u.creation_time::date = sampling_time.date
    GROUP BY
      sampling_time.date;
    

    【讨论】:

    • 酷。不知道这种技术。
    • 但是,我希望获得在该时间点之前注册的用户总数,而不是窗口。知道如何更改您的查询来做到这一点吗?
    • 你是什么意思在那个时间点之前(SELECT COUNT(*) FROM users WHERE creation_time &lt; '2014-11-01') 部分正是为此目的 - 添加在该日期之前添加的所有用户。
    • 但是,至少在我的执行中,也有一个下限。我想列出从一开始到那个时间点创建的用户数量。
    • 那么你可以把generate_series()和上面提到的count()一起去掉,直接从用户中选择,在where子句中没有任何日期条件。
    【解决方案2】:

    将您的查询更改为:-

    SELECT * FROM
    ((SELECT generate_series('2014-11-01'::timestamp, 
                        '2014-11-11'::timestamp, 
                        '1 day'::interval)) AS sampling_time, 
    (SELECT COUNT(*) 
     FROM users 
     WHERE creation_time<=sampling_time)AS created_before_sampling_time);
    

    我认为你的语法中一定有一些括号错误。

    【讨论】:

    • 谢谢。这似乎是一个简单的解决方案,但我得到ERROR: syntax error at or near "," LINE 4:'1 day'::interval)) AS sampling_time,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 2020-11-26
    相关资源
    最近更新 更多