anpera.net https://anpera.dyndns.org/phpbb3/ |
|
Nicht mehr existente User suchen https://anpera.dyndns.org/phpbb3/viewtopic.php?f=34&t=3605 |
Seite 1 von 2 |
Autor: | Bill Tür [ Mi 25 Apr, 2007 09:51 ] |
Betreff des Beitrags: | Nicht mehr existente User suchen |
Ich will ma n bischen aufräumen, bzw aufräumen lassen, also hätt ich in meiner setnewday gern folgendes: [php] $sql = "DELETE FROM items WHERE class='Möbel' AND owner= $blablubb "; db_query($sql); [/php] $blablubb soll dabei alle acctid´s darstellen, die nicht mehr existieren. wie muss ich $blablubb also definieren? |
Autor: | Nightborn [ Mi 25 Apr, 2007 10:05 ] |
Betreff des Beitrags: | |
$this->bbcode_second_pass_code('', 'SELECT items.owner,accounts.name FROM accounts RIGHT JOIN items ON accounts.acctid=items.owner GROUP BY items.owner ASC WHERE accounts.name=NULL;') Denke ich. |
Autor: | -DoM [ Mi 25 Apr, 2007 10:20 ] |
Betreff des Beitrags: | |
In der setnewday.php findest du folgendes Stück Code in der originalen Löschroutine: [php] $sql = "UPDATE items SET owner=0 WHERE owner=$row[acctid]"; db_query($sql); [/php] Soll heissen, wenn du nach acctids suchst, wirst du nicht wirklich fündig. Auch sollste die setnewday.php folgenden Code beinhalten: [php] db_query("DELETE FROM items WHERE owner=0 AND (class='Beute' OR class='Fluch' OR class='Geschenk' OR class='Schmuck' OR class='Waffe' OR class='Rüstung' OR class='Zauber')"); [/php] Soll heissen, dass an jedem neuen Tag die Items dessen Besitzer = 0 sind, sowieso gelöscht werden.... Sollte das bei dir nicht der Fall sein, solltest du deine setnewday.php mal kontrollieren, ob sich darin ein Fehler befindet, welches das Script nicht ausführen lassen. |
Autor: | Bill Tür [ Mi 25 Apr, 2007 12:17 ] |
Betreff des Beitrags: | |
ok, das bringt mich ein stück weiter, wobei meine frage eher losgelöst vom obigen beispiel zu verstehen war, da hab ich mich wohl weng missverständlich ausgedrückt. durch verschiedene mods hab ich noch mehr tabellen mit unnützen einträgen, die sich auf user beziehen, die nicht mehr da sind. für neulöschungen könnte ich das also in die setnewday und in die user.php reinnehmen nach obigem muster, aber das kann ich mir ja sparen, wenn ich eh die ganzen alten einträge löschen muss. |
Autor: | Harthas [ Mi 25 Apr, 2007 12:24 ] |
Betreff des Beitrags: | |
[php]$sql = "SELECT `acctid` FROM `accounts`"; $result = db_query($sql) or die(db_error(LINK)); $sql1 = "SELECT `id` FROM `bio`"; $result1 = db_query($sql1) or die(db_error(LINK)); for ($i=0;$i<db_num_rows($result1);$i++) { $row1 = db_num_rows($result1); $variable = 0; for ($y=0;$y<db_num_rows($result);$y++) { $row = db_num_rows($result); if ($row['acctid']==$row1['id']) { $variable = 1; } } if ($variable == 0) { $sql2 = "DELETE FROM `bio` WHERE `id` LIKE '".$row['id']."'"; db_query($sql2) or die(db_error(LINK)); } } db_free_result($result); db_free_result($result1);[/php] Ich habe letztens dieses kleine Codeschnippsel geschrieben... Um die Accounts- und die Bio-Tabelle abzugleichen. Ist allerdings nicht wirklich getestet, also noch mit Vorsicht zu geniessen. Die Tabellen zu ändern und es für deine Lauffähig zu machen, sollte eigentlich nicht allzu schwer sein. |
Autor: | Varius [ Mi 25 Apr, 2007 13:08 ] |
Betreff des Beitrags: | |
Wir haben bei unss auch da so ein Problem. Das in den verlassenen Häusern (Chaoskmaker System) die Sache der gelöschten Besitzer nicht verschwinden. Der von Dom gepostet Abschnitt fehlt bei uns total. Kann uns bitte einer sagen wie wir es bei uns einfügen müssen ? Das z.B. jeden neuen Tag die Sachen der gelöschten Benutzer verschwindet ? Der Abschnitt der User die automatisch gelöscht werden sieht so aus : [php] // can't send mail on anpera.net mail($row[emailaddress],"LoGD Charakter verfällt", " Einer oder mehrere deiner Charaktere von Legend of the Green Dragon auf ".$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME']." verfällt demnächst und wird gelöscht. Wenn du den Charakter retten willst, solltest du dich bald möglichst mal damit einloggen! Falls der Charakter ein Haus hatte, ist dieses bereits enteignet.", "From: ".getsetting("gameadminemail","postmaster@localhost.com") ); $sql = "UPDATE accounts SET sentnotice=1,house=0,housekey=0,marriedto=0 WHERE acctid='$row[acctid]'"; if ((int)$row[acctid]==(int)getsetting("hasegg",0)) savesetting("hasegg",stripslashes(0)); if ((int)$row[acctid]==(int)getsetting("hasamulett",0)) savesetting("hasamulett",stripslashes(0)); db_query($sql); $sql = "UPDATE houses SET owner=0 WHERE owner=$row[acctid]"; db_query($sql); $sql = "UPDATE items SET owner=0 WHERE owner=$row[acctid]"; db_query($sql); $sql = "DELETE FROM pvp WHERE acctid2=$row[acctid] OR acctid1=$row[acctid]"; db_query($sql) or die(db_error(LINK)); $sql = "UPDATE accounts SET charisma=0,marriedto=0 WHERE marriedto=$row[acctid]"; db_query($sql); } $old+=5; $delaccts = '0'; $sql = "SELECT acctid FROM accounts WHERE superuser<=1 AND (1=0\n" .($old>0?"OR (laston < \"".date("Y-m-d H:i:s",time()-3600*24*$old)."\")\n":"") .($new>0?"OR (laston < \"".date("Y-m-d H:i:s",time()-3600*24*$new)."\" AND level=1 AND dragonkills=0)\n":"") .($trash>0?"OR (laston < \"".date("Y-m-d H:i:s",time()-3600*24*($trash+1))."\" AND level=1 AND experience < 10 AND dragonkills=0)\n":"") .")"; $result = db_query($sql); while ($row = db_fetch_assoc($result)) { $delaccts .= ','.$row['acctid']; if ($row['acctid']==getsetting("hasegg",0)) savesetting("hasegg","0"); } $sql = "DELETE FROM accounts WHERE acctid IN ($delaccts)"; db_query($sql) or die(db_error(LINK)); $sql = "UPDATE houses SET owner=0 WHERE owner IN ($delaccts)"; db_query($sql); $sql = "UPDATE items SET owner=0 WHERE owner IN ($delaccts) AND class='Schlüssel'"; db_query($sql); $sql = "DELETE FROM items WHERE owner IN ($delaccts) AND owner!=0"; db_query($sql); $sql = "DELETE FROM pvp WHERE acctid2 IN ($delaccts) OR acctid1 IN ($delaccts)"; db_query($sql) or die(db_error(LINK)); $sql = "DELETE FROM mail WHERE msgto IN ($delaccts)"; db_query($sql) or die(db_error(LINK)); $sql = "UPDATE accounts SET charisma=0,marriedto=0 WHERE marriedto IN ($delaccts)"; db_query($sql); // end cleanup [/php] und hier der Link der ganzen Setnewday.php von unseren Testserver. http://drache.crystal.hl-users.com/test ... 1&file=415 1000 Dank ![]() |
Autor: | Bill Tür [ Mi 25 Apr, 2007 14:16 ] |
Betreff des Beitrags: | |
Ich hab den Schnipsel von Harthas mal an eine meiner Tabellen angepasst und in die superuser gesetzt. [php] if ($_GET[op]=="blablubb"){ $sql = "SELECT `acctid` FROM `accounts`"; $result = db_query($sql) or die(db_error(LINK)); $sql1 = "SELECT `acctid` FROM `mailadressen`"; $result1 = db_query($sql1) or die(db_error(LINK)); for ($i=0;$i<db_num_rows($result1);$i++) { $row1 = db_num_rows($result1); $variable = 0; for ($y=0;$y<db_num_rows($result);$y++) { $row = db_num_rows($result); if ($row['acctid']==$row1['acctid']) { $variable = 1; } } if ($variable == 0) { $sql2 = "DELETE FROM `mailadressen` WHERE `acctid` LIKE '".$row['acctid']."'"; db_query($sql2) or die(db_error(LINK)); } } db_free_result($result); output("Blablubb.`n`n"); } [/php] Wenn ichs anklick, kommt zwar der output "Blablubb", aber an der tabelle ändert sich gar nix. |
Autor: | Eliwood [ Mi 25 Apr, 2007 16:20 ] |
Betreff des Beitrags: | |
Um ausnahmslos alle Items zu bekommen, die keinen gültigen Besitzer mehr haben, reicht (eigentlich...) folgendender Query: $this->bbcode_second_pass_code('', 'SELECT i.*, a.acctid FROM `items` as i LEFT OUTER JOIN `accounts` as a ON a.`acctid` = i.`owner` WHERE i.`class` IN ("Schmuck") AND a.acctid IS NULL ORDER BY i.`id` ASC') Achtung: Der Query nimmt auch alle angegeben Klassen des Wanderhändlers! Um das zu verhindern, muss man den Query erweitern: $this->bbcode_second_pass_code('', 'SELECT i.*, a.acctid FROM `items` as i LEFT OUTER JOIN `accounts` as a ON a.`acctid` = i.`owner` WHERE i.`class` IN ("Schmuck") AND i.`owner` != 0 AND a.acctid IS NULL ORDER BY i.`id` ASC') Mit den gesammelten Item-ID's kann man dann alle Items in einem Query löschen: $this->bbcode_second_pass_code('', 'DELETE FROM `items` WHERE `itemid` IN (5,6,12,500)') |
Autor: | Harthas [ Mi 25 Apr, 2007 18:46 ] |
Betreff des Beitrags: | |
[php]$sql = "SELECT `acctid` FROM `accounts`"; $result = db_query($sql) or die(db_error(LINK)); $sql1 = "SELECT `id` FROM `bio`"; $result1 = db_query($sql1) or die(db_error(LINK)); for ($i=0;$i<db_num_rows($result1);$i++) { $row1 = db_fetch_assoc($result1); for ($y=0;$y<db_num_rows($result);$y++) { $row = db_fetch_assoc($result); $acctid[] = $row['acctid']; } if (!in_array($row1['id'],$acctid)) { $sql2 = "DELETE FROM `bio` WHERE `id` LIKE ".$row1['id']; db_query($sql2) or die(db_error(LINK)); } } db_free_result($result,$result1);[/php] So. Dies hier ist inzwischen getestet, und so funktioniert es auch. Waren einige kleinere Denkfehler enthalten gewesen ;-) Und einen sehr grossen Flüchtigkeitsfehler in doppelter Ausführung... db_num_rows anstelle von db_fetch_assoc *Kopf gegen die Wand ditsch* |
Autor: | Nightborn [ Mi 25 Apr, 2007 19:10 ] |
Betreff des Beitrags: | |
Sorry daß ich so reinplatze... aber ein wenig was zu "effizienz" möchte ich loswerden. So... und jetzt, mit z.b. 400 usern die es zu löschen gäbe, macht das ding schlappe 400 einzelne (!) delete queries ich wette, ich schaffe das mit einer (!) Faktor 400 ist schonmal was. abgesehen vom dauernden aufrufen von db_num_rows (was z.b. bei 6000 usern 6000 funktionscalls entspricht) das immer wieder das gleiche rüberschubst. dann verschachtelst du die schleifen. bei 6000 usern läufst du also nochmal bei ca. 6000+ bios rüber.... aha... 6000*6000 = 360.000 durchläufe... nicht übel... da geht rechenleistung ^^ nach dem ersten $i durchlauf ... läufst du wieder in die $y schleife und ... es sind keine db_num_rows aus $result mehr da... dennoch läufst du weiter durch... 5999 mal. db_fetch_ liefert IMMER null zurück... und du fügst brav null in den acctid array...der am ende auch schlappe 360.000 einträge fassen dürfte... mal abgesehen, daß in_array bei so einer aufgeblähten zahl nicht mehr so flott wie bei 6000 ist... klaro.... Darüber, daß man das gleiche mit einer schönen JOIN abfrage (die ich so formuliert hab mit items) auch kriegt, sehr schnell und in *einer* delete query ... naja... ^^ hier wäre mal das gleiche codestück etwas schlanker: (achtung, ungetestet!) [php] $sql = "SELECT acctid FROM accounts"; $result = db_query($sql) or die(db_error(LINK)); $sql1 = "SELECT id FROM bio"; $result1 = db_query($sql1) or die(db_error(LINK)); while ($row=db_fetch_assoc($result)) { //befüllt die acctids $acctid[] = $row['acctid']; } while ($row=db_fetch_assoc($result1)) { //holt alle ids aus den bios $bioid[] = $row['id']; } //schneide aus bioid jene, die in acctid vorkommen $kill=array_diff($bioid,$acctid); //sammle für die löschabfrage, mit komma getrennt $numbers=implode(",",$kill); $sql="DELETE FROM bio WHERE id IN (".$numbers.");"; db_query($sql) or die(db_error(LINK)); //aufräumen db_free_result($result,$result1); [/php] |
Autor: | Harthas [ Mi 25 Apr, 2007 19:15 ] |
Betreff des Beitrags: | |
1. Brauchst dich nicht zu entschuldigen ;-) 2. Ich denke niemals an solche Zahlen, da ich in erster Linie für meine momentanen Ansprüche programmiere (Sprich: 4 Spieler in etwa). Sollte auch nur ein Denkanstoss sein. 3. Ich habe auch nie behauptet, dass es gut ist. Nur, dass es funktioniert. 4. Ich kenne schlichtwegs nicht alle möglichen Funktionen. 5. Habe ich auch gerade erst 1 Jahr an Erfahrung sammeln können. 6. Diese Lösung gefällt mir allerdings *g* Habe jedoch noch nie mit IN und MySQL gearbeitet, daher war es mir zwar vom sehen her bekannt, aber nicht wirklich präsent. |
Autor: | Nightborn [ Mi 25 Apr, 2007 19:55 ] |
Betreff des Beitrags: | |
Macht nix, ich hab 1,75 Jahre. Okay ^^ Ne, wenn Du programmierst, denk immer an solche Zahlen... effizienter Code der liegt, bleibt effizient... aber wenn Dein Spiel wächst, und Du Load Probleme (CPU Last) kriegst, wirst Dus merken. Und sowas zu finden im nachhinein ist ne schöne Arbeit. das mit den db_num_rows...das ist noch in 1.1.0 drin gewesen... haben wir jetzt erst raus. naja, es ist noch ne Menge zu tun, also keine Bange. Aber die Verschachtelung mit Query war schon stark. Normal reicht eine gut gejointe SQL Query (wie bei mir oben, nur statt mit SELECT mit DELETE) und die macht das dann. |
Autor: | Sylver [ Mi 25 Apr, 2007 19:56 ] |
Betreff des Beitrags: | |
Nightborn hat geschrieben: Sorry daß ich so reinplatze... aber ein wenig was zu "effizienz" möchte ich loswerden.
So... und jetzt, mit z.b. 400 usern die es zu löschen gäbe, macht das ding schlappe 400 einzelne (!) delete queries ich wette, ich schaffe das mit einer (!) Faktor 400 ist schonmal was. abgesehen vom dauernden aufrufen von db_num_rows (was z.b. bei 6000 usern 6000 funktionscalls entspricht) das immer wieder das gleiche rüberschubst. dann verschachtelst du die schleifen. bei 6000 usern läufst du also nochmal bei ca. 6000+ bios rüber.... aha... 6000*6000 = 360.000 durchläufe... nicht übel... da geht rechenleistung ^^ nach dem ersten $i durchlauf ... läufst du wieder in die $y schleife und ... es sind keine db_num_rows aus $result mehr da... dennoch läufst du weiter durch... 5999 mal. db_fetch_ liefert IMMER null zurück... und du fügst brav null in den acctid array...der am ende auch schlappe 360.000 einträge fassen dürfte... mal abgesehen, daß in_array bei so einer aufgeblähten zahl nicht mehr so flott wie bei 6000 ist... klaro.... Darüber, daß man das gleiche mit einer schönen JOIN abfrage (die ich so formuliert hab mit items) auch kriegt, sehr schnell und in *einer* delete query ... naja... ^^ hier wäre mal das gleiche codestück etwas schlanker: (achtung, ungetestet!) [php] $sql = "SELECT acctid FROM accounts"; $result = db_query($sql) or die(db_error(LINK)); $sql1 = "SELECT id FROM bio"; $result1 = db_query($sql1) or die(db_error(LINK)); while ($row=db_fetch_assoc($result)) { //befüllt die acctids $acctid[] = $row['acctid']; } while ($row=db_fetch_assoc($result1)) { //holt alle ids aus den bios $bioid[] = $row['id']; } //schneide aus bioid jene, die in acctid vorkommen $kill=array_diff($bioid,$acctid); //sammle für die löschabfrage, mit komma getrennt $numbers=implode(",",$kill); $sql="DELETE FROM bio WHERE id IN (".$numbers.");"; db_query($sql) or die(db_error(LINK)); //aufräumen db_free_result($result,$result1); [/php] Und wo muss ich das jetzt genau reinsetzen? |
Autor: | Bill Tür [ Mi 25 Apr, 2007 20:40 ] |
Betreff des Beitrags: | |
Eliwood: Versteh ich net. Aber ich werds mir ma anschaun und versuchen, ob ichs blick ^^ Nightborn: Danke. Eingebaut, umgeschrieben auf meine Tabellen, funzt. Einziges Prob: Geht nicht, wenn $numbers ein leeres ergebnis liefert. also für die superuser ok, für die setnewday ungeeignet. Harthas: Danke auch dir, deines auch eingebaut, weil Nightborns nur mit numerischen Werten funzt und ich für eine Tabelle den login vergleichen muss. Fazit: beide Lösungen haben mir geholfen und bei meinen 150 Usern auch nicht so sonderlich serverbelastend. Sylver: Am sinnvollsten in die superuser.php, außer Nightborn fixed noch das prob mit dem leeren ergebnis, dann könnte es auch in die setnewday. |
Autor: | Eliwood [ Mi 25 Apr, 2007 21:00 ] |
Betreff des Beitrags: | |
@Nighti: du sprichst mir aus der Seele ![]() 2 Querys. Mehr brauch ich nicht. ^^ |
Autor: | Nightborn [ Mi 25 Apr, 2007 22:39 ] |
Betreff des Beitrags: | |
1 reicht ![]() Aber war schon gesagt. Für leere Werte ändere: db_query($sql) or die(db_error(LINK)); in if ($kill!=array()) db_query($sql) or die(db_error(LINK)); --- für den Login... ja, da geht implode nicht so leicht, weil die '...' rum müssen. aber ist ja nicht das problem, oder? ![]() [php] while ($row=db_fetch_assoc($result)) { //befüllt die acctids $acctid[] = "'".$row['acctid']."'"; } while ($row=db_fetch_assoc($result1)) { //holt alle ids aus den bios $bioid[] = "'".$row['id']."'"; } [/php] und schon könnte $row['id'] auch ein login sein. |
Autor: | Bill Tür [ Do 26 Apr, 2007 07:59 ] |
Betreff des Beitrags: | |
Öhm... ja... da hätt ich eigtl auch selbst drauf kommen können. ![]() Ich sollte mir doch wieder angewöhnen, die Bastelei aufs Woe zu verlegen, da bin ich wenigstens einigermaßen fit. *gg* Dann Danke nochmal an alle Beteiligten ![]() |
Autor: | Eliwood [ Do 26 Apr, 2007 16:36 ] |
Betreff des Beitrags: | |
Nightborn hat geschrieben: 1 reicht
![]() Aber war schon gesagt. Für leere Werte ändere: db_query($sql) or die(db_error(LINK)); in if ($kill!=array()) db_query($sql) or die(db_error(LINK));[/php] 2. Einer um die Datensätze zu holen, einer für das Löschen. Sofern man das ganze Zeugs auch loggen will. Will man nicht, so reicht einer, sofern Joins auch in Delete-Querys gehen. ^^ Und die ' ' kann man auch mit Join setzen: [php]$logins = array('John Milton', 'Lycidas', 'Wittgenstein', 'Diarmit'); $wherestring = '"'.implode('","', $logins).'"'; print $wherestring; # # Ausgabe: # "John Milton","Lycidas","Wittgenstein","Diarmit"[/php] Meins dürfte schneller sein bei grossen Datensätze. Oder gleich schnell. |
Autor: | Nightborn [ Do 26 Apr, 2007 20:21 ] |
Betreff des Beitrags: | |
Schwer zu sagen, 2 String adds pro Durchlauf. Ja, normal schon. Aber man müsste implode untersuchen, dann kann mans genau sagen. Aber das sind Kleinigkeiten gegen 400 queries... =) |
Autor: | Harthas [ Di 01 Mai, 2007 13:36 ] |
Betreff des Beitrags: | |
[php]$sql="DELETE FROM `bio` WHERE `id` NOT IN (SELECT `acctid` FROM `accounts`);"; db_query($sql) or die(db_error(LINK));[/php] Eine Frage.... Würde oben stehendes nicht auch funktionieren? Wäre ja ausserdem noch kürzer ^^ |
Seite 1 von 2 | Alle Zeiten sind UTC + 1 Stunde |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |