我知道有关累积总数的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';
等等
答案 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 |