2016-04-21 5 views
2

Ich habe folgende MySQL-Abfrage (timestamp ist in Unix Zeit, natürlich):kumulative Summe von einzigartigen Elemente durch ein anderes Element in einem verschachtelten Array sortiert

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)); 

Dies erzeugt so etwas wie dieses:

$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 
); 

ich möchte es zu etwas machen wie folgt aus:

$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 
); 

Dies ist, was ich habe tr ied, aber ich merkte erst später, dass es die Einzigartigkeit für einen bestimmten Zeitpunkt nur ist die Pflege, nicht das gesamte Array als ich beabsichtige, es zu tun:

$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); 
} 

Grundsätzlich ist der Zweck die kumulative Summe der Anzahl der produzieren usr_id 's pro Tag und stellen Sie sicher, dass usr_id nur als eine über das gesamte Array gezählt wird, dh. Machen Sie eine kumulative Summe von Unique usr_id 'sortiert nach Tag.

Wenn Sie Ideen zur besseren Optimierung der MySQL-Abfrage haben, ist das auch willkommen.

BEARBEITEN: Ich möchte die "Kumulation" über das gesamte Array passieren, nicht nur pro Tag, wie in meinem Beispiel Ausgabe, dh. Tag 1 ist 1, Tag 2 ist 3 (1 + 2), Tag 3 ist 5 (3 + 2) ... usw.

+0

Möchten Sie immer, dass die ID am frühesten Datum (oder einem bestimmten Datum) gezählt wird, und versuchen Sie, die Daten zweimal zu überspringen? – DaveCoast

+0

@DaveCoast was wichtig ist, ist, dass es nach Datum aufsteigend sortiert ist, und ich möchte, dass IDs, die bereits an einem beliebigen Datum verwendet wurden, weggelassen werden. – webeno

+0

Es wird interessant sein, eine elegante Lösung zu sehen. Ich würde es in 2 Schritten tun müssen, eine Abfrage Gruppierungs-ID und Min-Datum, dann zählen Sie die IDs mit einer laufenden Summe in PHP. – DaveCoast

Antwort

2

Sie können erste Gruppe Unique User von Tag wie folgt aus:

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

Dann können Sie einen Array aller Benutzer erstellen, Vereinigung jeden Benutzer Tag auf sie und das Ergebnis davon zählen zu erhalten die kumulative Summe.

+0

Ich habe die Frage in der Zwischenzeit bearbeitet und dem ursprünglichen Array eine zusätzliche Zeile hinzugefügt, um besser zu demonstrieren, was ich will: Die zusätzliche Zeile hat dieselbe ID (2) wie die Duplikate von '2011/6/20', Ihr Skript Es wird nur eine Duplikation geben, die eine in '2011/6/20', aber die eine im neuen Datum ignoriert, also wird sie auch zur Zählung hinzugefügt, anstatt sie wegzulassen ... updated your eval: https: //3v4l.org/pKcJj - das Endergebnis sollte 5 sein, nicht 6 ... hoffe, das macht Sinn ... :( – webeno

+0

Oh ja, ich habe vergessen, wie array_merge numerische Schlüssel behandelt. Ich habe in Array Union (+) und es scheint jetzt richtig zu funktionieren. https://3v4l.org/TvOGJ –

+0

Das ist es, Mann !! Vielen Dank! – webeno

1

Ich würde das in SQL tun.

Etwas in diese Richtung - das ist Pseudo-Code, nicht wirklich SQL natürlich, weil ich MSSQL-Entwickler bin, aber Idee macht Sinn.

Hier werden zuerst alle eindeutigen Benutzer-IDs und ihre Daten ausgewählt. Dann werden sie nach Daten gruppiert. Danach einfach in PHP laufen und addieren.

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

Dies ist nur eine Zählung innerhalb des angegebenen Datums, tut nicht die Kumulation, aber ich denke, ich könnte es einfach in PHP tun, so ist dies eigentlich ein guter Vorschlag, danke. – webeno

+0

Ist nicht der COUNT der eindeutigen IDs pro Tag, wonach Sie suchen? Dies sollte es tun. – Alexus

+0

Ja, aber ich möchte es auch über das gesamte Array kumulieren, sorry, wenn das nicht aus der Frage klar war, lassen Sie mich es bearbeiten ... – webeno