获取count_()其中created_date是累积的,基于日期

时间:2016-04-28 03:04:31

标签: mysql aggregate-functions

我知道有关累积总数的SO有几个答案。我已经进行了实验,但没有找到解决问题的方法。

Here是一个sqlfiddle。

我们有一个包含两个字段的联系人表,eid和create_time:

eid create_time
991772  April, 21 2016 11:34:21
989628  April, 17 2016 02:19:57
985557  April, 04 2016 09:56:39
981920  March, 30 2016 11:03:12
981111  March, 30 2016 09:36:48

我想在每个月末选择每月新联系人的数量以及联系人数据库的大小。按年和月的新联系人很简单。对于每个月末的联系人表格的大小,我做了一些研究和found what looked to be a straight forwards method

set @csum = 0;
select
   year(c.create_time) as yr,
   month(c.create_time) as mth,
   count(c.eid) as new_contacts,
   (@csum + count(c.eid)) as cumulative_contacts
from
  contacts c
group by
  yr,
  mth

但这会让我意想不到的结果。

如果我跑:

select count(*) from contacts where date(create_time) < current_date

我得到表146中的记录总数。

因此我预计使用@csum的查询中的最后一行在2016年4月有146个。它只有3个?

我的目标是字段cumulative_contacts: 用于例如记录2016年1月。

select count(*) from contacts where date(create_time) < '2016-02-01';

二月份的记录会有:

select count(*) from contacts where date(create_time) < '2016-03-01';

等等

3 个答案:

答案 0 :(得分:1)

试试这个:fiddele

这里有一个&#34;大于或等于&#34;加入,所以每个组&#34;包含&#34;以前的所有值。时代12部分,将洞穴比较转化为月份。我确实提供了这个解决方案,因为它不依赖于MySql。 (可以在很少或没有更改的情况下在许多其他DB上实现)

select dates.yr, dates.mth, dates.new_contacts, sum(NC.new_contacts) as cumulative_new_contacts
from (
    select
       year(c.create_time) as yr,
       month(c.create_time) as mth,
       count(c.eid) as new_contacts
    from
      contacts c
    group by
      year(c.create_time),
      month(c.create_time)
) as dates
left join 
(
    select
       year(c.create_time) as yr,
       month(c.create_time) as mth,
       count(c.eid) as new_contacts
    from
      contacts c
    group by
      year(c.create_time),
      month(c.create_time)
) as NC
on dates.yr*12+dates.mth >= NC.yr*12+NC.mth
group by 
    dates.yr, 
    dates.mth,
    dates.new_contacts   -- not needed by MySql, present here for other DBs compatibility
order by 1,2

答案 1 :(得分:1)

试试这个,从你的sql做一点修改;)

CREATE TABLE IF NOT EXISTS `contacts` (
  `eid` char(50) DEFAULT NULL,
  `create_time` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

INSERT INTO `contacts` (`eid`, `create_time`) VALUES
('991772', '2016-04-21 11:34:21'),
('989628', '2016-04-17 02:19:57'),
('985557', '2016-04-04 09:56:39'),
('981920', '2016-03-30 11:03:12'),
('981111', '2016-03-30 09:36:48');

SET @csum = 0;
SELECT t.*, @csum:=(@csum + new_contacts) AS cumulative_contacts
FROM (
    SELECT YEAR(c.create_time) AS yr, MONTH(c.create_time) AS mth, COUNT(c.eid) AS new_contacts
    FROM contacts c
    GROUP BY yr, mth) t

输出结果是

| yr   | mth | new_contacts | cumulative_contacts | 
 ------ ----- -------------- ---------------------
| 2016 | 3   | 2            | 2                   | 
| 2016 | 4   | 3            | 5                   | 

答案 2 :(得分:1)

这个sql将获得累积总和并且非常有效。它首先对每一行进行编号,然后将其用作累积总和。

SELECT s1.yr, s1.mth, s1.new_contacts, s2.cummulative_contacts
FROM
   (SELECT
       YEAR(create_time) AS yr,
       MONTH(create_time) AS mth,
       COUNT(eid) AS new_contacts,
       MAX(eid) AS max_eid
    FROM
       contacts
    GROUP BY
       yr,
       mth
    ORDER BY create_time) s1 INNER JOIN
       (SELECT eid, (@sum:=@sum+1) AS cummulative_contacts
    FROM
       contacts INNER JOIN
       (SELECT @sum := 0) r
    ORDER BY create_time) s2 ON max_eid=s2.eid;

--Result sample--
|   yr | mth | new_contacts | cumulative_contacts |
|------|-----|--------------|---------------------|
| 2016 |   1 |            4 |                 132 |
| 2016 |   2 |            4 |                 136 |
| 2016 |   3 |            7 |                 143 |
| 2016 |   4 |            3 |                 146 |