SQL-Abfrage mit OR - aber wie?

Fragen zu allen Themen rund ums Programmieren außerhalb von phpBB können hier gestellt werden - auch zu anderen Programmiersprachen oder Software wie Webservern und Editoren.
Antworten
Benutzeravatar
SemiX
Mitglied
Beiträge: 154
Registriert: 05.09.2004 19:39
Wohnort: NRW
Kontaktdaten:

SQL-Abfrage mit OR - aber wie?

Beitrag von SemiX »

Also eigentlich hatte ich gehofft, dass ich selbst drauf komme, aber nun...bin ich mit meinem Latein am Ende :oops: Ursache allen Übels ist folgende SQL-Abfrage:

Code: Alles auswählen

    $sql = "SELECT t.topic_id
  	FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p, " . VOTE_DESC_TABLE . " v
  	WHERE (t.topic_vote = 0
      AND t.topic_status < 2
  		AND t.topic_last_post_id = p.post_id
      AND p.post_time < $archive_topics_older_than)

      OR  (t.topic_vote = 1
      AND t.topic_status < 2
  		AND t.topic_last_post_id = p.post_id
      AND p.post_time < $archive_topics_older_than
      AND t.topic_id = v.topic_id
      AND v.vote_start+v.vote_length < " . time() . ")";
Nun, was soll sie machen? Im Prinzip will ich die Themen ausgeben, die...
a.) ...älter als z.B. 90 Tage sind und keine Umfrage besitzen und
b.) ...älter als z.B. 90 Tage sind und eine Umfrage besitzen, die bereits abgelaufen ist
(unbegrenzt lange gehende Umfragen sind hier nicht berücksichtigt)

Verarbeitet wird das dann durch eine while- und for-Schleife, die problemlos funktioniert. Der obige Schnippsel tuts auch, was er soll, nur gibt er mir die entsprechenden Themen doppelt aus. Sprich habe ich die Themen 1,2,3 und Thema 3 ist eine zeitlich begrenzte Umfrage, dann verarbeitet die for-Schleife die topic_id's in dieser Reihenfolge: 1,2,1,2,3.


Ich habe überlegt, ob ich das OR vielleicht falsch angewendet habe. Daher habe ich die sql-Abfrage mal auf folgendes reduziert:

Code: Alles auswählen

  $sql = "SELECT t.topic_id
  	FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p, " . VOTE_DESC_TABLE . " v
  	WHERE t.topic_vote = 0
      AND t.topic_status < 2
  		AND t.topic_last_post_id = p.post_id
      AND p.post_time < $archive_topics_older_than";
Nun gibt mir der Scherzkeks aber die topic_id's 1,2,1,2 aus. Erst wenn ich das , " . VOTE_DESC_TABLE . " v rausnehme, macht ers richtig. Und da ich prinzipiell neugierig bin: Wo hab ich den Wald in Brand gesetzt?

Danke schonmal, SemiX :)


EDIT: Auf den Rat von cYbercOsmOnauT hin Klammern eingefügt...
Zuletzt geändert von SemiX am 17.08.2006 20:50, insgesamt 1-mal geändert.
Kein Privatsupport. Das Forum leistet gute Hilfe- und bessere als ich allemal... (:
Benutzeravatar
cYbercOsmOnauT
Ehemaliges Teammitglied
Beiträge: 3820
Registriert: 18.02.2004 23:02
Wohnort: Göttingen
Kontaktdaten:

Beitrag von cYbercOsmOnauT »

Bevor ich mir Deinen Query genauer ansehe, hier ein erster Rat: Verwende bei solch komplexen boolschen Operationen immer Klammern. Damit Du sicher gehst, das diese auch richtig ausgeführt werden.

Beispiel:
a AND b OR c AND d

Weißt Du aus dem Kopf welche Wertigkeit welche boolsche Operation hat und somit zuerst durchgeführt wird? Ich nicht. Dann lieber so schreiben:
(a AND b) OR (a AND d)
und Du bist auf der sicheren Seite.

Grüße,
Tekin
• prof. phpbb-Installation, Reparatur, Rettung nach Hackattacken, sowie PHP/JS Programmierung aller Art
Zend Certified Engineer, Linux Administrator und die Sicherheit von 34 Jahren Programmiererfahrung
• Interesse? Kontakt unter t.birduezen@web-coding.eu
Benutzeravatar
Banger
Ehemaliges Teammitglied
Beiträge: 375
Registriert: 03.05.2005 21:53
Wohnort: Düsseldorf
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von Banger »

SemiX hat geschrieben:

Code: Alles auswählen

  $sql = "SELECT t.topic_id
  	FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p, " . VOTE_DESC_TABLE . " v
  	WHERE t.topic_vote = 0
      AND t.topic_status < 2
  		AND t.topic_last_post_id = p.post_id
      AND p.post_time < $archive_topics_older_than

      OR  t.topic_vote = 1
      AND t.topic_status < 2
  		AND t.topic_last_post_id = p.post_id
      AND p.post_time < $archive_topics_older_than
      AND t.topic_id = v.topic_id
      AND v.vote_start+v.vote_length < " . time();
Hi Semix,
vorerst würde ich die Query mal aufräumen, zwecks Übersichtlichkeit:

Code: Alles auswählen

$sql = 'SELECT t.topic_id
          FROM '.TOPICS_TABLE.' AS t
          JOIN '.POSTS_TABLE.' AS p
            ON p.post_id = t.last_post_id
           AND p.post_time < '.$archive_topics_older_than.'
     LEFT JOIN '.VOTE_DESC_TABLE.' AS v
            ON v.topic_id = t.topic_id
         WHERE t.topic_vote BETWEEN 0 AND 1
           AND t.topic_status < 2
           AND (v.topic_id IS NULL
                OR
                v.vote_start+v.vote_length < '.time().')
      GROUP BY t.topic_id';
Diese Form ist ressourcensparender (vulgo: schneller :-)), da der JOIN zur (recht großen) POSTS_TABLE erst nach Erfüllung der WHERE-Bedingung erfolgt. Zudem sind die Bedingungen so kompakter; die doppelten Bedingungen aus Deinem OR-Zweig können so auf jeweils eine reduziert werden.

Gerade bei einer Mischung von AND und OR empfehle ich immer, Klammern zu verwenden, das erhöht die Übersichtlichkeit und minimiert die Fehleranfälligkeit phänomenal. Das war bei Dir aber nicht ausschlaggeben, und um auf den Punkt zu kommen: das GROUP BY fehlte :-D
Benutzeravatar
SemiX
Mitglied
Beiträge: 154
Registriert: 05.09.2004 19:39
Wohnort: NRW
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von SemiX »

Diese Form ist ressourcensparender (vulgo: schneller :-)), da der JOIN zur (recht großen) POSTS_TABLE erst nach Erfüllung der WHERE-Bedingung erfolgt. Zudem sind die Bedingungen so kompakter; die doppelten Bedingungen aus Deinem OR-Zweig können so auf jeweils eine reduziert werden.
Danke danke danke! Ich könnt dich knuddeln :D

Group by - arg nie benutzt :oops: Über Join hab ichs auch probiert nur...ich blick da noch nicht durch die Syntax, also hab ichs wieder verworfen. Selbst mein Wälzer hier hilft mir da nicht weiter. Mal sehen ob ich irgendwas Erklärfreundliches im Netz finde... *hust*

SemiX
Kein Privatsupport. Das Forum leistet gute Hilfe- und bessere als ich allemal... (:
Benutzeravatar
Banger
Ehemaliges Teammitglied
Beiträge: 375
Registriert: 03.05.2005 21:53
Wohnort: Düsseldorf
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von Banger »

SemiX hat geschrieben:Über Join hab ichs auch probiert nur...ich blick da noch nicht durch die Syntax, also hab ichs wieder verworfen. Selbst mein Wälzer hier hilft mir da nicht weiter. Mal sehen ob ich irgendwas Erklärfreundliches im Netz finde... *hust*
Hi SemiX,
vielleicht hilf Dir das hier weiter: http://little-idiot.de/mysql/mysql-118.html
Benutzeravatar
SemiX
Mitglied
Beiträge: 154
Registriert: 05.09.2004 19:39
Wohnort: NRW
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von SemiX »

Mal sehn, ist auf jeden Fall ausführlicher als das, was ich bis jetzt so gefunden habe. Aber heute schwirrt mir der Kopf ;)

Noch eine letzte Frage: Irgendeine Idee, wie man den SQL-Code umstellen könnte, damit auch zeitlich unbegrenzte Themen nicht erfasst werden? Die tragen ja 0 als Wert für vote_length und sind damit kleiner als der aktuelle Timestamp.. :-?
Kein Privatsupport. Das Forum leistet gute Hilfe- und bessere als ich allemal... (:
Benutzeravatar
Banger
Ehemaliges Teammitglied
Beiträge: 375
Registriert: 03.05.2005 21:53
Wohnort: Düsseldorf
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von Banger »

SemiX hat geschrieben:Irgendeine Idee, wie man den SQL-Code umstellen könnte, damit auch zeitlich unbegrenzte Themen nicht erfasst werden? Die tragen ja 0 als Wert für vote_length und sind damit kleiner als der aktuelle Timestamp.. :-?
So?

Code: Alles auswählen

$sql = 'SELECT t.topic_id
          FROM '.TOPICS_TABLE.' AS t
          JOIN '.POSTS_TABLE.' AS p
            ON p.post_id = t.last_post_id
           AND p.post_time < '.$archive_topics_older_than.'
     LEFT JOIN '.VOTE_DESC_TABLE.' AS v
            ON v.topic_id = t.topic_id
         WHERE t.topic_vote BETWEEN 0 AND 1
           AND t.topic_status < 2
           AND (v.topic_id IS NULL
                OR
                (v.vote_length > 0 
                AND
                v.vote_start+v.vote_length < '.time().'))
      GROUP BY t.topic_id';
Benutzeravatar
SemiX
Mitglied
Beiträge: 154
Registriert: 05.09.2004 19:39
Wohnort: NRW
Kontaktdaten:

Re: SQL-Abfrage mit OR - aber wie?

Beitrag von SemiX »

Banger hat geschrieben: So? [Codebox]
arg [ externes Bild ] - womit bewiesen wäre, dass meine Konzentration zum gegenwärtigen Zeitpunkt wirklich Banane ist. Nochmals Danke! :grin:

SemiX
Kein Privatsupport. Das Forum leistet gute Hilfe- und bessere als ich allemal... (:
Antworten

Zurück zu „Coding & Technik“