[SQL] Schleife durch Query ersetzen |
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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
---
HackV1 | Nazrapedia | Spirits | YDK
Diese Nachricht wurde geändert von: Yhoko |
 Profil
Website
Editieren
Zitieren
|
languitar
Foren-Team
Beiträge: 2795 |
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.
|
 Profil
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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.
---
HackV1 | Nazrapedia | Spirits | YDK
Diese Nachricht wurde geändert von: Yhoko |
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
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; |
---
/* Moser [efm] */
Diese Nachricht wurde geändert von: moser |
 Profil
Website
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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.
---
HackV1 | Nazrapedia | Spirits | YDK
Diese Nachricht wurde geändert von: Yhoko |
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
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];
}
|
---
/* Moser [efm] */
|
 Profil
Website
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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.
---
HackV1 | Nazrapedia | Spirits | YDK
Diese Nachricht wurde geändert von: Yhoko |
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
Ä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!
---
/* Moser [efm] */
|
 Profil
Website
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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.
---
HackV1 | Nazrapedia | Spirits | YDK
|
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
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!)
---
/* Moser [efm] */
|
 Profil
Website
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
Es ging mir mehr um die Performance, denn bei mehreren 1000 Wohnungen (= mehrere 2*1000 Querys) geht das ganz schön auf die CPU.
---
HackV1 | Nazrapedia | Spirits | YDK
|
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
Ok, folgendes:
1. Du legst eine Tabelle flat_count an:
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.
---
/* Moser [efm] */
|
 Profil
Website
Editieren
Zitieren
|
Yhoko
Otto-Normal-Poster Threadstarter
Beiträge: 49 |
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
---
HackV1 | Nazrapedia | Spirits | YDK
|
 Profil
Website
Editieren
Zitieren
|
moser
Pixelschubser
Beiträge: 21 |
Bitteschön, gern geschen...
---
/* Moser [efm] */
|
 Profil
Website
Editieren
Zitieren
|