WebWork Magazin - Webseiten erstellen lassen, Online Medien, html

Webhoster, Webhosting Provider und Domain registrieren

Home | Registrieren | Einloggen | Suchen | Aktuelles | GSL-Webservice | Suleitec Webhosting
Reparatur-Forum | Elektro forum | Ersatzteilshop Haushalt und Elektronik


Homepage und Webhosting-Forum

Scripte und Programme für PHP, MYSQL. Diskussionen zur Programmierung im Web. Fragen zu CMS, Blogsoftware, Shops, Newsletter und vielen weiteren Scripten.


Forum » PHP & MySQL » [SQL] Schleife durch Query ersetzen » Antworten
Benutzername:
Passwort: Passwort vergessen?
Inhalt der Nachricht: Fett | Kursiv | Unterstrichen | Link | Bild | Smiley | Zitat | Zentriert | Quellcode| Kleiner Text
Optionen: Emailbenachrichtigung bei Antworten
 

[SQL] Schleife durch Query ersetzen
von moser
Bitteschön, gern geschen...
von Yhoko
Danke, das klingt vielversprechend.

Nach einem Blick in die MySQL-Manual werde ich mich wohl auch mal an Locks machen, ich denke damit ist das Problem ausreichend sauber gelöst
von moser
Ok, folgendes:

1. Du legst eine Tabelle flat_count an:
flat_id
count_users


die befüllst Du wie folgt mit Daten:
INSERT INTO flat_count VALUES SELECT flat_id, count(user_id) FROM flat_users GROUP BY flat_id;


2. Nun überprüfst Du fortan wie folgt:
Du liest diese Tabelle als "alten Stand" ein und vergleichst Ihn zeilenweise mit dem bislang oft genug geposteten Query. Und nur dort wo unstimmigkeiten auftreten, aktualisierst Du punktgenau eben genau diese Wohnung.


von Yhoko
Es ging mir mehr um die Performance, denn bei mehreren 1000 Wohnungen (= mehrere 2*1000 Querys) geht das ganz schön auf die CPU.
von moser
Ach so. Dann entschuldige meine Wortwahl.
Aber ich hatte mal ein ähnliches Problem (da ging es um Scores und Ranking-Scores bei einem Quiz) und habe mich letztendlich dafür entschieden bei den Schleifen zu bleiben. Es mag Dir primitiv erscheinen, aber es hat einen sehr gewichtigen Vorteil:

Dynamik. Denn so schließt Du aus, dass fehlerhafte Updates, Dir deine gesamte Tabelle zerhauen. Zudem: Ein Server verkraftet das schon, ein paar Datensätze aus einer Datenbank zu holen. (Limit sind 2GB Daten pro Tabelle!)


von Yhoko
Ich glaub wir reden aneinander vorbei, ich brauch kein Resultat sondern will in meiner Tabelle die Anzahl user jeder Wohnung aktualisieren. Da ich keine Möglichkeit fand ein solches Query zu formulieren mache ich das umständlich mit einer Schleife, die erst alle Wohnungen abklappert und für jede Wohnung die User zählt und das ganze wieder in die Tabelle zurückschreibt. Und genau von diesem primitiven Ansatz möchte ich loskommen.
von moser
Ähm, vielleicht solltest Du noch mal das Kapitel über mysql-Funktionen im PHP-Manual lesen.

Du sendest 1 (in Worten: ein) Query ab, das dir ein Result liefert.
Dieses Result kannst Du nunmal (sofern es mehr als eine Datenreihe beinhaltet) nur über eine Schleife auslesen. Das ist nunmal sprachbedingt durch PHP.

Ich betone nochmals: Auf die Datenbank greifst Du dennoch nur einmal zu!
von Yhoko
Das ist genau das was ich im 1. Posting schon schrieb; du vergisst das Update-Statement. Das Problem ist dass ich die Schleife loswerden will.
von moser
Ja, wo ist jetzt das Problem?

SELECT flat_id, count(user_id) from flat_users GROUP BY flat_id;


Dazu folgender Code:
1: 
2: 
3: 
4: 
5: 
6:
while ($row = mysql_fetch_row($result)) {
     $flat_id = $row[0];
     $anzahl_mieter = $row[1];
}


von Yhoko
Nein users und flats sind einzeln; flat_users stellt die n:n Verbindung zwischen den beiden dar:

users
- ID
- Username

flats
- ID
- Address

flat_users
- flat_id
- user_id


Es geht mir auch mehr grundsätzlich darum wie man so ein Query aufbaut wo man im ersten Gedankene eine Schleife draus machen will. Also z.B. für jeden Eintrag in der DB einen Wert von irgendwo anders berechnen... Subquerys wären wohl genau das was ich brauche, sind nur leider nicht verfügbar.

Sprich, dein Code hilft mir nicht weiter da dies nur das Auslesen der Daten beschreibt, was mit "SELECT count(*) FROM flat_users WHERE flat_id=$id" bereits geschieht. Es geht mir aber darum diese Ausgabe direkt in ein Update-Statement einfliessen zu lassen wie im 1. Beitrag bereits beschrieben.
von moser
Es wäre dazu recht interessant zu wissen, wie die Tabellen strukturiert sind.
Gesetzt dem Fall, dass du in flat_users die einzelnen Mieter (unique) den Wohnungen zuordnest, wäre das folgende denkbar:

SELECT wohnungen, COUNT(user) FROM table_name GROUP BY wohnungen;
von Yhoko
Nein keine Update-Schleife.

Ich habe eine Tabelle Wohnungen (flats), Personen (user) und Mieter (flat_users). Da eine Wohnung mehrere Personen als Mieter haben kann und eine Person auch mehrere Wohnungen mieten kann ist die 3. Tabelle notwendig. Aus Performancegründen möchte ich die Anzahl Personen in einer Wohnung aber direkt in der Wohnungsliste festhalten und um diese Zahl zu berechnen brauche ich bislang die Schleife.

Der Code geht also alle Wohnungen durch und zählt für jede Wohnung die Anzahl Personen aus der Mieterliste. Was ich suche ist also eine SQL-Zeile, die ungefähr das Macht:

UPDATE flats AS f SET users = SELECT count(*) FROM flat_users AS fu WHERE fu.flat_id=f.id


Ich arbeite auf MySQL 4.0.12, AFAIK sind Subquerys da noch nicht vorhanden; ich denke aber es gibt da einen eleganten Weg das zu lösen. Wichtig ist, dass es möglichst wenig SQL-Zugriffe gibt, am liebsten also ein Einzeiler.
von languitar
Soll das eine Art Update-Script sein, was ab und zu mal ausgeführt wird, oder wann soll das laufen und was genau soll das tun? Schreib doch mal deine Tabellenstruktur auf und was genau du machen willst.
von Yhoko
Hallo,

um die Anzahl Mieter in einer Wohnung herauszufinden verwende ich eine Schleife, die alle Wohnungen durchgeht, in der Tabelle zählt wieviele Mieter es gibt und diesen Wert in die Wohnung schreibt. Nicht sehr elegant, daher würde ich gerne einen besseren Weg finden um dies zu lösen. Hier mein Code:

// Update count
foreach( query_Rows( "SELECT id FROM flats" ) as $flat )
{
$count = query_Value( "SELECT count(*) FROM flat_users WHERE flat_id=" . $flat['id'] );
query( "UPDATE flats SET users=$count" );
}


Danke im Voraus,

Yhoko

Nach oben