随时间计算不同的总数

时间:2015-09-24 14:55:12

标签: sql

我有以下数据:

UniqueID    SenderID    EntryID Date
1           1           1       2015-09-17
2           1           1       2015-09-23
3           2           1       2015-09-17
4           2           1       2015-09-17
5           3           1       2015-09-17
6           4           1       2015-09-19
7           3           1       2015-09-20

我需要的是:

3   2015-09-17
4   2015-09-19
4   2015-09-20
4   2015-09-23

第一列是截至该日期的唯一总条目。因此,例如,发件人1和条目1的23/9上的条目不会增加总列数,因为17/9中存在重复。

我如何有效地理想这样做,而不加入与你最终得到的相同的表是非常大的查询,这是不切实际的。我在Postgres中用OVER()完成了类似的操作,但遗憾的是这在此设置中不可用。

我也可以在代码中执行此操作 - 但我又要在db系统之外进行计算,然后重新导入。对于数百万行,此过程需要数天,理想情况下只需要几小时。

2 个答案:

答案 0 :(得分:1)

OVER是大多数数据库中可用的ANSI标准功能。你在计算什么是用户的开始,你可以用累积的总和来做到这一点:

select startdate,
       sum(count(*)) over (order by startdate) as CumulativeUniqueCount
from (select senderid, min(date) as startdate
      from table t
      group by senderid
     ) t
group by startdate
order by startdate;

这应该适用于任何支持窗口功能的数据库,例如Oracle,SQL Server 2012 +,Postgres,Teradata,DB2,Hive,Redshift,仅举几例。

编辑:

您需要left join才能获取数据中的所有日期:

select d.date,
       sum(count(d.date)) over (order by d.date) as CumulativeUniqueCount
from (select distinct date from table t) d left join
     (select senderid, min(date) as startdate
      from table t
      group by senderid
     ) t
     on t.startdate = d.date
group by d.date
order by d.date;

答案 1 :(得分:0)

感谢Gordon Linoff的基本查询。但是,对于不增加累计总和的日期,它不会返回行。

要获取这些额外的行,您需要包含一个额外的子查询,列出表中的所有不同日期。然后你离开加入Gordon的查询+一些小调整以获得理想的结果:

select d.SomeDate,
       sum(count(t.SenderId)) over (order by d.SomeDate)
from (select distinct SomeDate
        from SomeTable) d
left join (select SenderId, min(somedate) as MinDate
            from SomeTable
           group by SenderId) t
  on d.SomeDate = t.MinDate
group by d.SomeDate
order by d.SomeDate;