Auge: UNION in IN() als Teil einer WHERE-Klausel? Zwischenstand.

Beitrag lesen

Hallo

Muss es unbedingt eine einzelne Monster-Query sein, oder kannst du das Union-Ergebnis erstmal in einer temporären Tabelle ablegen und diese dann nutzen?

Nein, eine Zwischenlagerung fällt aus,

Mit temporärer Tabelle meinte ich den im System enthaltenen Mechanismus, eine solche Tabelle für die aktuelle Sitzung zu erstellen, die dann am Ende von selbst wieder verschwindet.

Ich weiß nicht so recht, ob das sinnvoll ist. Ich habe bisher einfach noch keinen Anwendungsfall für temporäre Tabelle gehabt. Daher kann ich die Vor- und Nachteile bezüglich Performanz und Komplexität überhaupt nicht einschätzen.

Wenn ich mit PHP den Query zur Erstellung einer temporären Tabelle absetze, bleibt die Tabelle bis zum schließen der Verbindung vorhanden?

Vielleicht kann man noch das LEFT JOIN entsorgen und stattdessen den Wert user_name (ist ja anscheinend nur dieser eine) per correlated Subquery in der Select-Klausel ermitteln. Das nimmt ein Stück Komplexität aus der FROM-Klausel raus, und diese Tabelle wird für das Erstellen der Zwischenergebnismenge nicht benötigt.

Da der Name aus der Eintrags- oder der Benutzertabelle kommen kann, habe ich das mit einem IF() gelöst. Leider wird die „user_id“, so sie nicht vorhanden ist, mit einer „0“ statt mit NULL abgespeichert. Daher kommt der Vergleich mit ent2.user_id > 0. Die „user_id“ fällt dafür aus dem Abfrageergebnis heraus.

Stattdessen kommt nun das Feld „edited“ mit einem Zeitstempel oder NULL als Beweis für einen geänderten Eintrag hinzu. Zudem kommt ein zweites IF() hinzu, mit dem zwischen den Zeitstempeln für den Eintrag bzw. der letzten Bearbeitung gewählt wird. Mit diesem wird die gesamte Ergebnismenge sortiert.

Das alles lässt die Ausführungszeit für den Query beim ersten Aufruf zwar etwa auf nicht ganz das Doppelte der vorher vorhandenen Lösung steigen, aber danach, aus dem Cache, ist der Query so schnell, wie gehabt.

SELECT
 ent1.id,
 (IF(ent2.user_id > 0, (SELECT user_name FROM userdata WHERE userdata.user_id = ent2.user_id), ent2.name)) AS name,
 ent2.time,
 ent2.edited,
 ent2.subject,
 ent2.category,
 (IF(ent2.edited IS NOT NULL, ent2.edited, entries.time)) AS orderTime
FROM ((
 SELECT id FROM entries WHERE spam = 0 ORDER BY time DESC LIMIT 6)
  UNION (
 SELECT id FROM entries WHERE spam = 0 ORDER BY edited DESC LIMIT 6))
 AS ent1
 INNER JOIN entries AS ent2
  ON ent1.id = ent2.id
 ORDER BY orderTime DESC
 LIMIT 6

Tschö, Auge

--
Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
Toller Dampf voraus von Terry Pratchett