2016-04-21 169 views
2

我有以下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

回答

2

可以先組獨特的用戶一天是這樣的:

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

1

我會做,在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