PostgreSQL:计算系列中时间范围之前创建的项目

时间:2014-11-12 09:59:53

标签: sql postgresql subquery date-range

描述

考虑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对用户进行子查询吗?

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

将您的查询更改为: -

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

我认为你的语法必须有一些括号错误。