累积总和

问题描述:

我有以下MySQL查询(timestamp是在Unix时间,很明显):累积总和

SELECT usr_id, CONCAT(YEAR(FROM_UNIXTIME(timestamp)), "/", MONTH(FROM_UNIXTIME(timestamp)), "/", DAY(FROM_UNIXTIME(timestamp))) as date_stamp 
FROM table 
ORDER BY YEAR(FROM_UNIXTIME(timestamp)), MONTH(FROM_UNIXTIME(timestamp)), DAY(FROM_UNIXTIME(timestamp)); 

这产生这样的事情:

$arr = array(
    array('usr_id'=>3, 'date_stamp'=>'2011/6/6'), 
    array('usr_id'=>2, 'date_stamp'=>'2011/6/20'), 
    array('usr_id'=>2, 'date_stamp'=>'2011/6/20'), // same id and date as above 
    array('usr_id'=>5, 'date_stamp'=>'2011/6/20'), // same date as above 
    array('usr_id'=>1, 'date_stamp'=>'2011/6/21'), 
    array('usr_id'=>4, 'date_stamp'=>'2011/6/21'), // same date as above 
    array('usr_id'=>2, 'date_stamp'=>'2011/6/21'), // same date as above... 
     //... and same id as a day before 
); 

我愿把它弄成这个样子:

$arr = array(
    array('sum'=>1, 'date_stamp'=>'2011/6/6'), 
    array('sum'=>3, 'date_stamp'=>'2011/6/20'), // +2 as one of the 3... 
     //... for this date was a duplicate 
    array('sum'=>5, 'date_stamp'=>'2011/6/21'), // +2 as one of the 3... 
     //... was already there on a different day 
); 

这就是我TR IED,但我后来才意识到,这只是照顾唯一的给定日期,而不是整个阵列,因为我想让它做的事:

$sum = 0; 
$tempRes = array(); 
$result = array(); 
$date = null; 
foreach($arr as $row) 
{ 
    $date = $row['date_stamp']; 
    if (!in_array($row['usr_id'], $tempRes)) 
     $tempRes[$date][] = $row2['usr_id']; 
} 
foreach ($tempRes as $date2 => $ids) 
{ 
    $sum += count($ids); 
    $result[] = array($date2, $sum); 
} 

基本目的是要产生的次数的累积总和usr_id的每天,并确保相同usr_id只在整个阵列中计为一个,即。按天排序的唯一usr_id累计总和。

如果你有更好的优化MySQL查询的想法,那就是欢迎了。

编辑:我想“累积”发生在整个阵列上,而不仅仅是每天,如我的示例输出,即。 1天1,2天3(1 + 2),3天5(3 + 2)......等

+0

您是否总是希望在最早日期(或特定日期)计算的ID,并且您是否试图避免将数据两次传递? – DaveCoast

+0

@DaveCoast重要的是它按日期升序排序,并且我希望在任何日期已经使用的id被省略。 – webeno

+0

看到一个优雅的解决方案将是有趣的。我必须分两步完成:查询分组ID和最短日期,然后用PHP中的运行总数来统计ID。 – DaveCoast

可以先组独特的用户一天是这样的:

foreach ($arr as $item) { 
    $days[$item['date_stamp']][$item['usr_id']] = 1; // value is irrelevant 
} 

然后你就可以创建所有用户的数组,工会每一天的用户到它,并计算的,其结果得到累计金额。

$all_users = array(); 
foreach ($days as $day => $users) { 
    $all_users = $all_users + $users; 
    $result[] = array('sum' => count($all_users), 'date_stamp' => $day); 
} 
+0

我在此期间编辑了问题,并在原始数组中添加了一行,以更好地展示我想要的内容:多余的行与“2011/6/20”副本相同(id为2),脚本将只处理'2011/6/20'中的一个副本,但会忽略新日期中的一个,因此它会将该值添加到计数中而不是忽略它...更新了您的评估:https: //3v4l.org/pKcJj - 最终的结果应该是5,6不...希望这是有道理... :( – webeno

+0

噢,我忘了数字如何对待array_merge键我改到阵列工会(+。 ),它现在似乎工作正常。https://3v4l.org/TvOGJ –

+0

就是这样,男人!!非常感谢! – webeno

我会做,在SQL。

类似的规定 - 这是伪代码,当然不是真正的SQL,因为我是MSSQL开发,但想法是有道理的。

这将首先选择所有的唯一的用户ID和他们的日期。然后它会按日期分组。在此之后,只需在PHP中运行并加起来即可。

SELECT 
    COUNT(usr_id) 
    date_stamp 
    ts 
FROM 
    (
     SELECT 
      DISTINCT usr_id, 
      timestamp as ts, 
      CONCAT(YEAR(FROM_UNIXTIME(timestamp)), "/", MONTH(FROM_UNIXTIME(timestamp)), "/", DAY(FROM_UNIXTIME(timestamp))) as date_stamp 
     FROM 
      table 
    ) 
GROUP BY 
    date_stamp 
ORDER BY 
    ts 
+0

这只是在给定的日期内提供一个计数,不会做累计,但我想我可以在PHP中做,所以这实际上是一个很好的建议,谢谢。 – webeno

+0

是不是每天唯一ID的COUNT是你以后?这应该做到这一点。 – Alexus

+0

是的,但我也希望它在整个阵列上累积,对不起,如果不是从这个问题不清楚,让我编辑... – webeno