evilmoe
Goto Top

MySQL - Abfrage vereinfachen

Ich habe hier 2 SQL Befehle die in einer Schleife ausgeführt werden. Die Schleife hatt 100 und mehr durchläufe! Dem entsprechen dauert das generieren der Seite auch ein wenig.

Als ersten führ ich ein normalen "SELECT id, datei" aus auf einer Tabelle. Die läuft dann in der Schleife durch und gibt diese aus. Aber ich brauche noch 2 Werte. Und deswegen habe ich noch 2 Abfragen in der Schleife. Die sehen so aus:

 // $row->id ist die ID die von dem "SELECT *" kommt. 
 $sql = sprintf("SELECT COUNT(id) as votes FROM votes WHERE trackid='%d' LIMIT 1", $row->id);  

 
 $sql = sprintf("SELECT COUNT(id) as anz FROM votes WHERE trackid='%d' AND ip='%s' LIMIT 1", $row->id, md5($_SERVER['REMOTE_ADDR']));  

Gibt es eine möglichkeit das einfacher/schneller zu lösen so das der Server schneller die Ergebnisse liefert?

Content-Key: 93420

Url: https://administrator.de/contentid/93420

Printed on: April 24, 2024 at 02:04 o'clock

Member: Biber
Biber Aug 01, 2008 at 22:00:52 (UTC)
Goto Top
Moin EvilMoe,

geht es nicht mit einem SubSelect?
SELECT t.id, t.datei, v1.votes, v2.anz
From tabelle t, 
(select trackid, count(id) as votes from votes
group by trackid ) v1,
(select trackid, ip, count(id) as Anz from votes
group by trackid, ip ) v2
Where 
t.id = v1.trackid and
t.id = v2.trackid and
v2.ip = md5($_SERVER['REMOTE_ADDR']);  

Grüße
Biber
P.S. Ist natürlich nur getippt, nicht getestet....
Member: EvilMoe
EvilMoe Aug 01, 2008 at 23:09:42 (UTC)
Goto Top
Danke erstmal.

ich habe nun folgenden SQL:

  
     $sql = "SELECT t.id, t.datei, v1.votes, v2.votet FROM   
   		tracks as t,
		(SELECT trackid, COUNT(id) as votes FROM votes GROUP BY trackid) as v1 ,
		(SELECT ip, trackid, COUNT(id) as votet FROM votes GROUP BY trackid, ip ) as v2 
			
			WHERE t.id = v1.trackid AND
				  t.id = v2.trackid AND 
				  v2.ip = '".md5($_SERVER['REMOTE_ADDR'])."'  
		";  
Dort habe ich noch 2 Probleme.

Ich brauche alle Ergebnisse aus der Tabelle tracks AUCH wenn die ID nicht in votes ist (dort ist das die trackid).

Man bekommt nur ein Ergebnis wenn die IP übereinstimmt. Muss aber auch gehen wenn sie nicht übereinstimmt (dann soll votes=0 sein und votet auch).

Tut mir leid. Ich bin leider nicht so ein SQL Freak...
Member: Biber
Biber Aug 02, 2008 at 01:26:06 (UTC)
Goto Top
Moin EvilMoe,

Ich bin leider nicht so ein SQL Freak...
Ich auch nicht - ich kann auch in meiner Küche viel pfiffigere Sachen zusammenbraten als hier im Forum...

Wenn Du auch die Sätze ohne Child-Summen (bzw. mit Summe 0) brauchst, dann klappt es mit dem Inner Join (alle Sätze, die in allen verknüpften Tabellen sind) natürlich nicht.
Das hatte ich falsch verstanden bzw. interpretiert.
  
     $sql = "SELECT t.id, t.datei,   
    Case when v2.votet is null then 0
            else v1.votes
        end as votes,
      , Case when v2.votet is null then 0
        else v2.votet
        end as votet
       FROM tracks as t 
  LEFT JOIN
     (SELECT trackid, COUNT(id) as votes 
       FROM votes GROUP BY trackid) as v1 on t.id = v1.trackid
   Left Join  
      (SELECT ip, trackid, COUNT(id) as votet 
        FROM votes 
       Where ip = '".md5($_SERVER['REMOTE_ADDR'])."'  
     GROUP BY trackid, ip ) as v2  on t.trackid=v2.id";  

Grüße
Biber
Member: EvilMoe
EvilMoe Aug 02, 2008 at 07:35:33 (UTC)
Goto Top
In der SQL Abfrage hab ich jetzt einen Syntax Fehler.

Ich verstehe auch gerade die Case anfragen nicht ganz. Das Feld votet gibts nicht. Ich hatte den nur als Alias verwendet. votet soll true ergeben wenn unter votes die trackid und die IP übereinstimmt andernfalls false.

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' Case when v2.votet is null then 0 else v2.votet end as votet ' at line 5  
Member: Biber
Biber Aug 02, 2008 at 17:17:10 (UTC)
Goto Top
Moin EvilMoe,

Sorry, aber meiner Meinung ist da nur ein Komma zuviel - zwischen den beiden CASE-Anweisungen sind zwei aufeinanderfolgende.

Sonst sehe ich keinen Entwurfsfehler.
Nur Testen kann ich es nicht, weil ich SQL nur aus Kreuzworträtseln kenne und nix auf dem Rechner habe.

Grüße
Biber
Member: EvilMoe
EvilMoe Aug 02, 2008 at 20:15:59 (UTC)
Goto Top
Ohh das hab ich auch übersehen. Nun sind wir der Lösung schon ganz nahe! Funktioniert schonmal sehr gut. Aber ein Fehler konnt ich noch festellen.

v1.votes liefert 0 ergebnisse obwohl 1 Treffer ist. Wenn 2 Treffer sind zeigt er auch 2 an aber wenn nur einer ist eben nicht.

Aber wenn man selber dafür gevotet hat zeigt er eine 1 an! Also wenn die IP übereinstimmt.

Momentan siehts so aus (unten haste 2 Werte vertauscht, war aber nicht tragisch konnte es ausfindig machen):

SELECT t.id, t.datei, 
    		Case when v2.votet is null then 0 else v1.votes end as votes,
      		Case when v2.votet is null then 0 else v2.votet end as votet
       		FROM tracks as t
			  LEFT JOIN
				 (SELECT trackid, COUNT(id) as votes 
				   FROM votes GROUP BY trackid) as v1 on t.id = v1.trackid
			   Left Join  
				  (SELECT ip, trackid, COUNT(id) as votet 
					FROM votes 
				   Where ip = '".md5($_SERVER['REMOTE_ADDR'])."'  
				 GROUP BY trackid, ip ) as v2  on t.id=v2.trackid ORDER BY datei


EDIT: Muss mich nochmal korregieren. v1.votes ergibt immer 0 wenn man nicht auch dafür gevotet hat (also die IP muss auch stimmen sonst immer 0)!
Member: Biber
Biber Aug 03, 2008 at 03:34:16 (UTC)
Goto Top
Moin EvilMoe,

Man bekommt nur ein Ergebnis wenn die IP übereinstimmt. Muss aber auch gehen wenn sie nicht übereinstimmt (dann soll votes=0 sein und votet auch).

Jepp, so habs ich umgesetzt. Und nach Deiner letzten Beschreibung tut es das ja - works as designed.
Wenn "votes" immer als votes-Wert angezeigt werden soll, dann logischerweise statt des ersten CASE-Geraffels einfach "votes" schreiben.

Und bitte diesen Beitrag auf "erledigt" setzen.

Danke
Biber
Member: EvilMoe
EvilMoe Aug 03, 2008 at 06:57:47 (UTC)
Goto Top
Okay. So funktioniert das wunderbar!!! Vielen danke Biber!


So siehts fertig aus face-smile
SELECT t.id, t.datei, 
    		Case when v1.votes is null then 0 else v1.votes end as votes,
      		Case when v2.votet is null then 0 else v2.votet end as votet
       		FROM tracks as t
			  LEFT JOIN
				 (SELECT trackid, COUNT(id) as votes 
				   FROM votes GROUP BY trackid) as v1 on t.id = v1.trackid
			   Left Join  
				  (SELECT ip, trackid, COUNT(id) as votet 
					FROM votes 
				   Where ip = '".md5($_SERVER['REMOTE_ADDR'])."'  
				 GROUP BY trackid, ip ) as v2  on t.id=v2.trackid ORDER BY datei