PHP -> Arrays addieren

fixxxxxi

Erfahrenes Mitglied
Hallo,

ich habe ein Gewinnspiel gebastelt, bei dem die SQL Tabelle u.a. wie folgt aufgebaut ist:

datum - user_richtig

Nun wird bei richtiger Antwort, die UserID in die Zelle eingetragen, die dem Datum entspricht.

1 - |123||456||789|
2 - |123||456||789|
3 - |123|
4 - |789|
...
24 - |456||789|

Die Punkte die der User erreicht ergeben sich aus dem Datum. Sprich - Datum 1, Frage richtig beantwortet = 1 Punkt - Datum 24, Frage richtig beantwortet = 24 Punkte. Nun möchte ich die Punkte der einzelnen User addieren und in einer Rangliste ausgeben. Sprich das Array sortieren und im Anschluß sortieren.

Zu meinem Ansatz:

Wenn ich mir das richtig überlegt habe, müsste ich zuerst 24 einzelne Abfragen machen, wo ich die einzelnen userIDs, zu dem entsprechendem Datum holen:

PHP:
//abfrage
$ranking_sql  = mysql_fetch_array(safe_query("SELECT user_richtig FROM `".PREFIX."quiz` WHERE nummer='".$datum."'"));

//userIDs trennen
$ranking_user   = explode("||", $ranking_sql['user_richtig']);

Nun habe ich alle UserIDs getrennt vom jeweiligem Datum, wo sich allerdings ein weiteres Problem verbirgt. Denn die UserIDs werden in dem Format |userID| eingetragen und nicht ||userID. Dies benötige ich, damit ich bei einer Abfrage der userID entsprechend mit % arbeiten kann. Also in der Abfrage %|userID|% um einen Treffer zu erzielen. Aber bei dem explode trennt er ja bei ||, was jedoch beim ersten und letztem Inhalt des Arrays nicht zutrifft.

Wie kann ich diese beiden Probleme lösen?

LG
 
Zuletzt bearbeitet:
1. Normalform:

Jedes Attribut der Relation muss einen atomaren Wertebereich haben.
Quelle

Du solltest dein Datenbankmodell da ein wenig anpassen. Du hast z.B. eine Tabelle mit den IDs deiner User (die Usertabelle vermutlich) und dann eine Relation für die Datumse, die die User gelöst haben:

Datum|Userid
1|123
1|456
2|123
...

Du hast also nur eine UserID pro Datensatz. Dann kannst du mit den Aggregationsfunktionen von MySQL wunderbar arbeiten...
 
Dafür ist es erstens zu spät, und zweitens befinden sich in der Tabelle noch weitere Werte.

datum | frage | antwort1 | antwort2 | antwort3 | ergebnis | user_richtig | user_alle

datum = 24
frage = welcher buchstabe ist der erste im alphabet?
antwort1 = B
antwort2 = A
antwort3 = C
ergebnis = antwort2
user_richtig = |123|
user_alle = |123||456||789|

Ich überprüfe mit dieser Tabelle zusätzlich ob der User bereits die Frage zB. beantwortet hat.

PHP:
$i = 1;
while ($i <= 24) {
$date=$i++;
$ranking_sql  = mysql_fetch_array(safe_query("SELECT user_richtig FROM `".PREFIX."quiz` WHERE nummer='".$date."'"));
echo '<br/>Datum/Punkte:'.$date++.' - UserIDs: '.$ranking_sql[0].'<br/>'; 
}

gibt folgendes aus:

Datum/Punkte:1 - UserIDs: |95||707||625||1255||1190|...
Datum/Punkte:2 - UserIDs: |95||707||625||1255||1190|...
Datum/Punkte:3 - UserIDs: |85||95||1237||637||707||1693|...
...

Damit muss man doch irgendwie weiterkommen******
 
Zuletzt bearbeitet:
Welch katastrophale Datenhaltung.

Nichtsdestotrotz ist es nicht unlösbar. entweder du machst das über Reguläre Ausdrücke, mit explode und anschliessender bereinigung oder mit einem 3-Punkte-Plan.

Hier mal der 3-Punkte-Plan
1) Ersetzen aller '||' durch ','
->Resultat: ein String der mit einem '|' beginnt und mit einem ebensolchen endet. Dazwieschen sind die User durch ',' getrennt
2) Ersetzen aller '|' durch nichts, also ''
->Resultat: ein komaseparierter String mit den Usern
3) explode() mit dem Trennzeuichen ',' durchführen
->Resultat: Ein Array mit allen User-IDs

Und so sieht das aus
PHP:
$users = explode(',',(str_replace('|', '', str_replace('||', ',', $str))));

Wenn du die Speicherart noch ändern kannst, dann mach aus |user||user| besser user,user. Du kannst dann in MySQL direkt mit FIND_IN_SET() direkt einen User auslesen
SQL:
WHERE
    FIND_IN_SET('1255', '95,707,625,1255,1190');
 
Zuletzt bearbeitet von einem Moderator:
Danke schonmal vorab. Nun hab ich folgendes, womit schonmal die einzelnen user in einzelne Arrays pro tag gegliedert werden:

PHP:
$i = 1;
while ($i <= 24) {
$date=$i++;
$ranking_sql  = mysql_fetch_array(safe_query("SELECT user_richtig FROM `".PREFIX."quiz` WHERE nummer='".$date."'"));
$users = explode(',',(str_replace('|', '', str_replace('||', ',', $ranking_sql['user_richtig'])))); 

echo '<br/><b>Datum/Punkte:'.$date++.'.12.2010</b><br/>';

for ($x = 0; $x < sizeof($users); ++$x)
{
if (key($users)<10) $key_users='0'.key($users); else $key_users=key($users);
     
     echo "Arraywert: ".$key_users.", UserID: ".current($users)."<br>";
     next($users);
     
}

}

Ausgabe:

...
Arraywert: 00, UserID: 85
Arraywert: 01, UserID: 95

Datum/Punkte:2.12.2010
Arraywert: 00, UserID: 95
Arraywert: 01, UserID: 707
Arraywert: 02, UserID: 625
Arraywert: 03, UserID: 1255
Arraywert: 04, UserID: 1190
Arraywert: 05, UserID: 184
Arraywert: 06, UserID: 1653
Arraywert: 07, UserID: 1303
Arraywert: 08, UserID: 1414
Arraywert: 09, UserID: 331
Arraywert: 10, UserID: 259
Arraywert: 11, UserID: 2
Arraywert: 12, UserID: 79
Arraywert: 13, UserID: 27
Arraywert: 14, UserID: 762
Arraywert: 15, UserID: 339
Arraywert: 16, UserID: 841

Datum/Punkte:3.12.2010
Arraywert: 00, UserID: 85
Arraywert: 01, UserID: 95
...

Nun ist die Frage wie ich die Anzahl der einzelnen Userids addiere. Und nicht einfach nur addiere, sondern auch die Punkte der einzelnen Tage richtig addiere. Sprich wenn jemand am 2.12. richtig beantwortet hat 2 punkte addiert werden.

Mein Ziel ist letztendlich folgende Ausgabe:

Ranking:
Platz 1: UserID: 85 (5 Punkte)
Platz 2: UserID: 95 (4 Punkte)
...
 
Woher kommen die Punkte? 2.12 -A 2 Punkte. wer als am 2.12. richtig hat, kriegt 2 Punkte, wer am 3.12. richtig hat kriegt 3 Punkte?
 
PHP:
<?php 
//Array für die Punkteliste initialisieren
//Array('userid'=>punkte)
$punkteliste = array();

//SQL so umschreiben, dass das Datum und die Richtig-Liste ausgelesen werden
$sql = "SELECT datum, user_richtig FROM `".PREFIX."quiz` WHERE nummer='{$date}'";
$resut = mysql_query($result);


while($node = mysql_fetch_array($result)){
    //Alle Users aus der Richtig-Liste extrahieren
    $users = explode(',',(str_replace('|', '', str_replace('||', ',', $node['user_richtig']))));
    //Alle User durchgehen
    foreach($users as $user){
        //Der Punkteliste die Punkte (Tag) hinzuzählen     
        $punkteliste[$user] = $punkteliste[$user]+date('j',strtotime($node['datum']));
    }
    
}    
//Die Punkteliste umgekehrt sortieren
arsort($punkteliste);    
//Die Rangliste erstellen
//Array(Rang-1 => 'userid'
$rangliste = array_values($punkteliste);
var_dump($punkteliste, $rangliste);  
?>
 
Nochmals Danke. Jedoch ist irgendetwas nicht richtig. Zum einen gibt es ja gar keine Spalte Datum in der SQL DB. Ist das kleinere Übel, habe date zu nummer umgeschrieben.

Was ich nicht so recht verstehe, woher nimmt Dein Code in der SQL Abfrage das $date? Weil date ist ja nirgends definiert :/ Oder sollte der Code in die while Schleife?

Wenn ich den Code so übernehme gibt er aus:

array(0) { } array(0) { }
 
$date habe noch aus deinen Zeilen weiter oben.
Ah, ich sehs jetzt, bei dir ist date eine Zahl, kein Datum.
Ja nimm den WHERE-Teil einfach raus. etnferne weiter unten die Datumsauswahl aus dem MySQL-Datum zu der direkten Nummer.

Ein Tipp, keine Zahl $date nennen. Keinen String $number nennen etc. Gibt nur verwirrung
 
Zurück