[Erledigt] SQL Abfrage sortieren

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.
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

@gn#36: Dank dir! Leider klappt es noch nicht ganz 100%tig. Irgendwie werden die mit Bildern immer noch nicht alphabetisch sortiert.

Hier mal zum selber ansehen:
http://www.springenderhund.de/forum,271 ... sen-d.html

Hab den Code etwas angepasst:

Code: Alles auswählen

if ($forum_row['forum_sort'] == "SORT_ALPHA")
{
	$topic_order = "bild_da DESC"; //t.topic_picture DESC, t.topic_title ASC";
}
else
{
	$topic_order = "topic_last_post_id DESC";
}
$sql = "(SELECT 1 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
      AND t.topic_type = " . POST_STICKY . "
      $limit_topics_time
      $ignore_tarbed
      AND t.topic_picture <> ''
      ORDER BY topic_title ASC
) UNION (SELECT 0 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
      AND t.topic_type = " . POST_STICKY . "
      AND t.topic_picture = ''
      $limit_topics_time
      $ignore_tarbed
      ORDER BY topic_last_post_id DESC)
   ORDER BY $topic_order
   LIMIT $start, ".$board_config['topics_per_page'];
@Xwitz
Ja das stimmt, nur hätte er Sie nicht anzeigen wollen wär meine antwort mit where richtig gewesen :wink:
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

Das Einfügen von ORDER BY bei einzelnen SELECT-Anweisungen in Klammern hat nur in Kombination mit LIMIT Auswirkungen. Andernfalls wird ORDER BY wegoptimiert.
...hmm dat is nix! :roll:

Habs jetzt so hinbekommen:

Code: Alles auswählen

$sql = "(SELECT 1 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      $limit_topics_time
      $ignore_tarbed
      AND t.topic_picture <> ''
      ORDER BY topic_title ASC
      LIMIT $start, ".$board_config['topics_per_page']."
) UNION (SELECT 0 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      AND t.topic_picture = ''
      $limit_topics_time
      $ignore_tarbed
      ORDER BY topic_last_post_id DESC
      LIMIT $start, ".$board_config['topics_per_page'].")";
Aber dann stimmt die Pagination nicht mehr. Hier ein Beispiel:

http://www.springenderhund.de/forum,260 ... sen-s.html
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

Nu hab ichs!

Ist zwar nicht ganz sauber, aber so geht es:

Code: Alles auswählen

$sql = "(SELECT 1 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      $limit_topics_time
      $ignore_tarbed
      AND t.topic_picture <> ''
      ORDER BY topic_title ASC
      LIMIT 0, 100
) UNION (SELECT 0 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      AND t.topic_picture = ''
      $limit_topics_time
      $ignore_tarbed
      ORDER BY topic_last_post_id DESC
      LIMIT 0, 100)
      LIMIT $start, ".$board_config['topics_per_page'];
Benutzeravatar
gn#36
Ehrenadmin
Beiträge: 9313
Registriert: 01.10.2006 16:20
Wohnort: Ganz in der Nähe...
Kontaktdaten:

Beitrag von gn#36 »

Hm, ich vermute mal dass das dann bei mehr als 100 Einträgen mit Bild nicht mehr funktionieren wird... Bist du sicher, dass die LIMIT Anweisungen innen benötigt werden? Ich würde die einfach ganz weglassen. LIMIT 0, 100 begrenzt ja lediglich auf 100 Einträge aus dem Bereich.
Begegnungen mit dem Chaos sind fast unvermeidlich, Aber nicht katastrophal, solange man den Durchblick behält.
Übertreiben sollte man's im Forum aber nicht mit dem Chaos, denn da sollen ja andere durchblicken und nicht nur man selbst.
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

Leider kann ich es nicht weglassen, da wie oben schon geschrieben gilt:
Das Einfügen von ORDER BY bei einzelnen SELECT-Anweisungen in Klammern hat nur in Kombination mit LIMIT Auswirkungen. Andernfalls wird ORDER BY wegoptimiert.
Habe es jetzt mal auf 10000 gesetzt und eingestellt, das er nur die geänderte Abfrage nimmt, wenn überhaupt ein Bild drin ist. d.H. Für normale Foren, wird die alte Abfrage genommen.

Ich denke damit kann ich leben! :wink:

Ich dank Dir nochmal für den Gedankenanstoss gn#36!
Benutzeravatar
gn#36
Ehrenadmin
Beiträge: 9313
Registriert: 01.10.2006 16:20
Wohnort: Ganz in der Nähe...
Kontaktdaten:

Beitrag von gn#36 »

Oh ok, das war mir nicht klar (habe ich wohl überlesen).

Dann wäre mein Vorschlag, einfach offset + gesamtlimit als grenze zu verwenden, damit sollte es auf der sicheren Seite sein. (Mehr als alles aus einem Bereich geht ja nicht). Hat das mit dem ORDER BY über beide SQL Abfragen nicht funktioniert? Wenn das alleine ausreichen würde bräuchte man derartige Konstrukte nicht.

Bei dem UNION Befehl muss man teilweise auch sehr vorsichtig sein, was unterschiedliche MYSQL Versionen angeht. Ich habe z.B. bei einer ziemlich komplexen Abfrage die Erfahrung gemacht, dass es mit der Version auf meinem PC - also der neueren Version - ohne Probleme funktionierte, die Version auf dem Server aber auf einen Syntaxfehler hinwies, den ich dann natürlich ewig gesucht habe. Ich glaube das war ein Problem mit Subselects oder so (also SELECT im SELECT). Das Entfernen des Subselects hat die Größe der SQL Abfrage mehr als verdoppelt...
Begegnungen mit dem Chaos sind fast unvermeidlich, Aber nicht katastrophal, solange man den Durchblick behält.
Übertreiben sollte man's im Forum aber nicht mit dem Chaos, denn da sollen ja andere durchblicken und nicht nur man selbst.
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

Nee, ein einfaches ORDER BY über beide Tabellen möchte ich nicht, da die ersten Beiträge so zusagen als Info gelten sollen, und danach Fragen und der gleichen gepostet werden können, was bedeutet Beiträge mit Bildern nach Alphabet und normale Beiträge nach Zeit (lastpostid DESC).

Wie meinst Du das als Offset?
Benutzeravatar
gn#36
Ehrenadmin
Beiträge: 9313
Registriert: 01.10.2006 16:20
Wohnort: Ganz in der Nähe...
Kontaktdaten:

Beitrag von gn#36 »

Ach so, die unterschiedliche Sortierung wüsste ich sowieso nicht wie man das anders machen könnte als mit UNION.

Zum Offset/LIMIT: Ich dachte anstatt eine feste Grenze zu verwenden die (zumindest theoretisch) irgendwann einmal Probleme verursachen wird könnte man das ganze dynamisch machen. Dazu verwendet man eben für beide Einzelabfragen das zu der gesamtabfrage passende LIMIT. Mehr als die im gesamt-LIMIT festgelegte Anzahl an Datensätzen kann nicht aus jeder der beiden Abfragen kommen, da aber noch ein offset definiert wird muss dieses noch hinzukommen, da ansonsten diese Datensätze nicht übersprungen werden könnten, wenn die Abfrage zusammengefügt wird.
-> BSP:

Code: Alles auswählen

(SELECT ... LIMIT 0, X ) UNION (SELECT ... LIMIT 0, Y ) LIMIT A, B
Wie müssen jetzt X und Y gewählt werden?
Wenn A = 0 ist, dann reicht es aus, wenn X = Y = B, denn mehr als B Datensätze können aus keiner der Tabellen verwendet werden.
Wenn aber A <> 0 dann muss X = Y = A + B, denn jetzt könnten weiterhin aus einer Abfrage alle Ergebnisse benötigt werden, aber diese werden DANACH noch per Offset im LIMIT verschoben, d.h. wenn wir nur B Datensätze auswählen würden würden die letzten (oder bei großem Offset sogar alle) Datensätze fehlen. Selektieren wir aber die Anzahl der gesuchten UND zusätzlich noch offset Datensätze gibt es dieses Problem nicht.
Begegnungen mit dem Chaos sind fast unvermeidlich, Aber nicht katastrophal, solange man den Durchblick behält.
Übertreiben sollte man's im Forum aber nicht mit dem Chaos, denn da sollen ja andere durchblicken und nicht nur man selbst.
Benutzeravatar
bgx
Mitglied
Beiträge: 228
Registriert: 30.11.2005 22:32
Kontaktdaten:

Beitrag von bgx »

Hmm...

Ich hab es jetzt so gemacht:

Code: Alles auswählen

$sqllimit=$start+$board_config['topics_per_page'];

$sql = "(SELECT 1 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      $limit_topics_time
      $ignore_tarbed
      AND t.topic_picture <> ''
      ORDER BY topic_title ASC
      LIMIT 0, $sqllimit
) UNION (SELECT 0 as bild_da,t.*, u.username, u.user_id, u2.username as user2, u2.user_id as id2, p.post_username, p2.post_username AS post_username2, p2.post_time, p2.post_edit_time
   FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
   WHERE t.forum_id = $forum_id
      AND t.topic_poster = u.user_id
      AND p.post_id = t.topic_first_post_id
      AND p2.post_id = t.topic_last_post_id
      AND u2.user_id = p2.poster_id
		AND t.topic_type <> " . POST_ANNOUNCE . "
		AND t.topic_type <> " . POST_STICKY . "
      AND t.topic_picture = ''
      $limit_topics_time
      $ignore_tarbed
      ORDER BY topic_last_post_id DESC
      LIMIT 0, $sqllimit)
      LIMIT $start, ".$board_config['topics_per_page'];
Denke, das kann man so lassen.

Dank Dir nochmal! :wink:
Antworten

Zurück zu „Coding & Technik“