Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
统计Postgresql中的累计总数_Sql_Postgresql_Aggregate Functions - Fatal编程技术网

统计Postgresql中的累计总数

统计Postgresql中的累计总数,sql,postgresql,aggregate-functions,Sql,Postgresql,Aggregate Functions,我使用count和group by获得每天注册的订阅者数量: SELECT created_at, COUNT(email) FROM subscriptions GROUP BY created at; 结果: created_at count ----------------- 04-04-2011 100 05-04-2011 50 06-04-2011 50 07-04-2011 300 我想得到的是每天用户的累计总数。我怎么得到这个 created_

我使用count和group by获得每天注册的订阅者数量:

  SELECT created_at, COUNT(email)  
    FROM subscriptions 
GROUP BY created at;
结果:

created_at  count
-----------------
04-04-2011  100
05-04-2011   50
06-04-2011   50
07-04-2011  300
我想得到的是每天用户的累计总数。我怎么得到这个

created_at  count
-----------------
04-04-2011  100
05-04-2011  150
06-04-2011  200
07-04-2011  500
使用:


我假设您每天只需要一行,并且仍然希望显示没有任何订阅的天数假设没有人订阅某个日期,您是否希望显示该日期以及前一天的余额?。如果是这种情况,您可以使用“with”功能:

with recursive serialdates(adate) as (
    select cast('2011-04-04' as date)
    union all
    select adate + 1 from serialdates where adate < cast('2011-04-07' as date)
)
select D.adate,
(
    select count(distinct email)
    from subscriptions
    where created_at between date_trunc('month', D.adate) and D.adate
)
from serialdates D
对于较大的数据集,是执行这类查询的最有效方法-表将只扫描一次,而不是像自联接一样,每个日期扫描一次。它看起来也简单多了PostgreSQL 8.4及更高版本支持窗口函数

这就是它看起来的样子:

SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM subscriptions
GROUP BY created_at;
在这里创建窗口;ORDER BY created_at意味着它必须将ORDER中created_at的计数相加

编辑:如果您想在一天内删除重复的电子邮件,可以使用sumcountdistinct电子邮件。不幸的是,这不会删除跨越不同日期的重复项

如果要删除所有重复项,我认为最简单的方法是使用子查询和DISTINCT ON。这会将电子邮件的日期归为最早的日期,因为我按创建的时间按升序排序,它会选择最早的日期:

SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM (
    SELECT DISTINCT ON (email) created_at, email
    FROM subscriptions ORDER BY email, created_at
) AS subq
GROUP BY created_at;
如果你在电子邮件上创建了一个索引,这个查询也不会太慢

如果您想进行测试,我就是这样创建示例数据集的

create table subscriptions as
   select date '2000-04-04' + (i/10000)::int as created_at,
          'foofoobar@foobar.com' || (i%700000)::text as email
   from generate_series(1,1000000) i;
create index on subscriptions (email, created_at);

最好的方法是使用日历表: 日历 日期, 整月, 四分之一整数, 半整数, 国际周, 整年


然后,您可以加入此表以对所需字段进行汇总。

我尝试了sums2.count,控制台出现错误:“聚合函数调用无法嵌套”,我的意思是COUNTs2.email,对不起。请查看我编辑过的解决方案。谢谢老兄!我正在处理一个更复杂的查询,您的结构很容易理解,因此易于实现。谢谢,使用函数也会很有用。学到了一些新东西。您可以使用内置函数来代替serialdates:generate_seriestimestamp'2011-04-04',timestamp'2011-04-07',interval'1 day',这是一个很棒的intgr,只是我的订阅表包含了大量重复的电子邮件行。所以我现在要做的就是将计数相加,但我仍然需要在以后的每个日期重新计算唯一的电子邮件。我用一个独特的on子查询更新了我的答案。它仍然比安德烈的答案快得多——可以在几秒钟内处理一百万行——但可能更复杂。关于generate_series函数的好提示!请注意,DISTINCT ON还可以转换为具有GROUP BY的等效查询;在这种情况下,选择电子邮件,MINcreated_at as created_at FROM subscriptions GROUP BY email。哪一个更有效可能会有所不同,尽管来自DISTINCT ON的就绪排序子查询似乎对窗口函数所需的排序有一些优势。我希望每月都有此功能,我需要如何更改此查询?我真的有点问题,这和我的总数无关。
SELECT created_at, sum(count(email)) OVER (ORDER BY created_at)
FROM (
    SELECT DISTINCT ON (email) created_at, email
    FROM subscriptions ORDER BY email, created_at
) AS subq
GROUP BY created_at;
create table subscriptions as
   select date '2000-04-04' + (i/10000)::int as created_at,
          'foofoobar@foobar.com' || (i%700000)::text as email
   from generate_series(1,1000000) i;
create index on subscriptions (email, created_at);