[PHP] Multiaccount erkennen Problem

  • Guten Tag,
    ich bin gerade dabei alle IPs mit den Usern aus der Datenbank zu vergleichen. Sinn war, dass erstmal alle Accounts gezählt werden, die die gleich IP-Adresse haben.
    Das Problem ist, dass die User doppelt gezählt werden. Außerdem werden sie sogar selbst gezählt bzw. gelistet.


    Ich komme nicht weiter und brauche Hilfe.


    Tabellenstruktur:


    Tabellensätze:


    Mein Code (1):

    $query = $dbh->prepare("SELECT `$mysql->db_acc_ip_id`, COUNT(*) as multiaccs FROM `$mysql->db_acc_ip_table` GROUP BY `$mysql->db_acc_ip_ip`");
    $query->execute();
    if($query->rowCount() == 0)
    {
    echo "<div class='alert alert-info'>Es wurden keine Multiaccounts gefunden.</br></div>";
    }
    else
    {
    echo "
    <table class='table table-hover'>
    <thead>
    <tr>
    <td><b>$labels->page_multiacc_table_item_1</b></td>
    <td><b>$labels->page_multiacc_table_item_2</b></td>
    <td></td>
    </tr>
    </thead><tbody>";


    while($result = $query->fetch())
    {
    echo "<tr>";
    echo "<td>".$mysql_funcs->getUserNameById($result[$mysql->db_acc_ip_id], $mysql, $dbh)."</td>";
    echo "<td>".$result["multiaccs"]."</td>";
    echo "<td><a href='?page=multiaccounts&details=".$result[$mysql->db_acc_ip_id]."'><span class='btn btn-sm btn-primary'>Details</span></a></td>";
    echo "</tr>";
    }
    echo "</tbody></table>";
    }


    Meine Ausgabe von Code (1):


    __________________________________________________________________________________________________


    Mein Code (2):

    if(isset($_GET["details"]))
    {
    $user_id = filter_var($_GET["details"], FILTER_SANITIZE_SPECIAL_CHARS);
    if($mysql_funcs->getUserLogIdbyId($user_id, $mysql, $dbh) > 0)
    {
    $query = $dbh->prepare("SELECT `$mysql->db_acc_ip_id` FROM `$mysql->db_acc_ip_table` WHERE `$mysql->db_acc_ip_ip` = :uip");
    $query->execute(array(":uip"=>$mysql_funcs->getUserIpById($user_id, $mysql, $dbh)));
    if($query->rowCount() == 0)header("location: home.php");


    echo "
    <table class='table table-hover'>
    <thead>
    <tr>
    <td><b>$labels->page_multiacc_table_item_1</b></td>
    <td><b>$labels->page_multiacc_table_item_2</b></td>
    <td></td>
    </tr>
    </thead><tbody>";


    while($result = $query->fetch())
    {
    echo "<tr>";
    echo "<td>".$mysql_funcs->getUserNameById($user_id, $mysql, $dbh)."</td>";
    echo "<td>".$mysql_funcs->getUserNameById($result[$mysql->db_acc_ip_id], $mysql, $dbh)."</td>";
    echo "<td></td>";
    echo "</tr>";
    }
    echo "</tbody></table>";
    }
    else header("location: home.php");
    }


    Meine Ausgabe von Code (2):


    Mein Problem liegt in den SQL Abfragen. Je mehr IPs dort eingetragen sind, desto öfter werden die gleichen Spieler aufgelistet.


    Beispiel:
    Tabelle:


    Ausgabe:


    Vielen Dank für jegliche Hilfe im Voraus.

  • Eine SQL Abfrage, welche übergreifend Multiaccounts überprüft ist schon einigermaßen Professionell.
    Habe gerade dein Schema bei dir nach gebaut, und ich muss zugeben dass mir keine Lösung ohne das schreiben einer Funktion eingefallen ist.


    Falls es nicht klappt würde ich dir empfehlen, ein Befehl zu bauen welcher einfach nur alle Datensätze mit gleichen IP Adressen wiedergibt, und den Rest in PHP zu erledigen.
    (DS durchgehen, Array zum Speichern von gleichen Accounts, String zum concatten der Spieler u.Ä. Dann mit einem Account anfangen).


    Dein Problem mit dem selbst Zählen welches du gesagt hattest lässt sich mit einem -1 lösen, da ein Account ja "gewollt" ist :)

    526C4Hj.png Mit freundlichen Grüßen,
    Noneatme

  • Gibt es einen speziellen Grund, warum Du das Filtern direkt in der Abfrage machen willst? - Ein besser, und sauberere Lösung wäre die Tabelle als Objekt abzubilden.
    (Alternativ auch als Cronjob die Abhängigkeiten in einer Tabelle abbilden)


    Speichere Deine IP-Adressen bitte niemals als varchar. Das ist ein altbekanntes Thema, wo es zu Problemen beim Vergleichen kommen kann. Von der Effizienz mal ganz weg.
    Interesssante Erklärung dazu:
    http://www.ebrueggeman.com/blo…ing-ip-addresses-in-mysql


    //edit 2:


    Du könntest es aber mal so versuchen


    SQL
    SELECT FIELD_IP_ADRESS, GROUP_CONCAT(DISTINCT FIELD_USERNAME)
    FROM TABLE_NAME
    GROUP BY FIELD_IP_ADRESS
    HAVING COUNT(DISTINCT FIELD_USERNAME) > 1
    ORDER BY COUNT(DISTINCT FIELD_USERNAME) DESC


    Sollte Dein Problem eigentlich lösen. Hier wird Dir ausgegeben, welche IP Adressen mehrfach vorkommen.

    Chief Technology Officer (CTO)


    Interesse an folgenden Domains?

    fivemp.de - planet-zoo.de

    Jetzt anschreiben :)

    Einmal editiert, zuletzt von Jony ()

  • Keine Ahnung wie du auf so eine Idee kommst. Es ist sauberer, performanter und deutlich einfacherer die Filterung direkt in der Query durchzuführen.

    Das mag vielleicht bei einer einzel Anwendung wie hier der Fall sein.


    Wenn Du Daten dann weiterverarbeiten willst, etc. kommst Du mit Deiner Art nicht weiter.
    Aber jeder so wie er mag.
    Es gab dazu aber letztens mal ein interessanten Artikel, der die Unterschiede mal genau aufgelistet hat. Muss ich nochmal suchen.


    //edit:
    Im Grunde hast Du ja recht mit der Annahme, das SQL die Filterung aufgrund von Indexen etc. besser machen kann.
    Da möchte ich Dir auch nicht widersprechen. Aber sobald Du größere Anzahl von Daten (Online-Shops) hast, wirst Du solche Filterungen durch SQL seltener bis gar nicht mehr vorfinden. (Ich rede hier jetzt nicht von Joins o.Ä.)


    Es hängt auch alles sehr viel mit dem Aufbau der Datenbank zusammen.

    Chief Technology Officer (CTO)


    Interesse an folgenden Domains?

    fivemp.de - planet-zoo.de

    Jetzt anschreiben :)

    Einmal editiert, zuletzt von Jony ()

  • Wenn man die weiterverarbeiten will dann joined man die entsprechende Tabelle, da hat er uns aber die entsprechende Tabelle bisher nicht gezeigt. Entsprechend - ja, es ist aktuell suboptimal geregelt, man würde es aber optimieren indem man es richtig macht nicht indem du irgendwelche Fachbegriffe um dich wirfst die nichts mit einem korrekten Workflow oder sonst irgendwas zu tun haben.


    //edit für deinen Edit:
    Doch, umso größer die Daten werden desto eher musst du die Last verteilen. Für jeden Datensatz ne neue Query abzufeuern ist extrem unperformant. Bei sehr großen Anwendungen würde man vorformatieren und cachen. Wie dein "Tabelle als Objekt umbilden" aussehen würde hast du uns bisher nicht gezeigt, für mich klingt das nur als wolltest du mit Fachbegriffen um dich werfen.

  • Wenn man die weiterverarbeiten will dann joined man die entsprechende Tabelle, da hat er uns aber die entsprechende Tabelle bisher nicht gezeigt. Entsprechend - ja, es ist aktuell suboptimal geregelt, man würde es aber optimieren indem man es richtig macht nicht indem du irgendwelche Fachbegriffe um dich wirfst die nichts mit einem korrekten Workflow oder sonst irgendwas zu tun haben.


    //edit für deinen Edit:
    Doch, umso größer die Daten werden desto eher musst du die Last verteilen. Für jeden Datensatz ne neue Query abzufeuern ist extrem unperformant. Bei sehr großen Anwendungen würde man vorformatieren und cachen. Wie dein "Tabelle als Objekt umbilden" aussehen würde hast du uns bisher nicht gezeigt, für mich klingt das nur als wolltest du mit Fachbegriffen um dich werfen.

    Ich werfe mit Sicherheit nicht mit "irgendwelchen" Begriffen um mich. Ist schließlich mein täglich Brot ;)


    Richtig die Last verteilen. Man verteilt aber die Last nicht komplett auf den SQL-Server. Wie Du schon selber richtig erkannt hast, ist die Verteilung der Aufgaben zwischen Webserver und SQL-Server wichtig. Es gibt sowieso keine Allgemeine Lösung. Die Vorgehensart ist immer abhängig davon, was für eine Anwendung man hat.
    Der Workflow ist hier relativ unwichtig. Es ist in großen Online-Shop-Systemen gang und gäbe die Datenbank fast 1:1 in PHP abzubilden. (Hier kommt wieder das Sprichtwort Objekt-Manager und Cache-Server zum Einsatz. Sprengt hier aber alles den Rahmen.)
    Und hier ist auch der Knackpunkt: Ich habe nirgendswo gesagt, dass man einen Query jedes mal absendet oder ähnliches.


    Die Diskussion ist hier aber auch nicht angebracht. Trägt nicht zur Lösung des Problems bei.


    //edit:
    Der Grund warum ich das mit den Objekten und Abbildung angesprochen habe war, dass ich davon ausgegangen bin das die Daten weiter verarbeitet werden sollten. Hier würde sich dann generell erstmal die Situation anders darstellen.

    Chief Technology Officer (CTO)


    Interesse an folgenden Domains?

    fivemp.de - planet-zoo.de

    Jetzt anschreiben :)

  • Ich arbeite bei einem recht großen Telekommunikationsanbieter mit riesigen Datenbanken und kann dir mit Sicherheit sagen: doch, du verteilst die Last auf die Datenbanken. Allein schon, weil du so nur exakt die richtigen Werte zurück bekommst und keinen Overhead an Daten hast, die du nur für die Berechnung brauchst.
    In großen Datenclustern gibt es dann eigene Systeme, die die Daten verarbeiten, und die Last wird wieder von der Datenbank weg genommen. Aber wenn du das nicht hast, solltest du immer möglichst viel die Datenbank machen lassen. Die kann das auch viel besser als irgendein Client. Die ist nämlich darauf optimiert.