Hallo,
Es müsste (so wie die Liste jetzt formatiert ist) immer genau die erste Zeile einer Gruppe übrig bleiben, das wäre das für mich gewünschte Ergebnis.
das sieht nach einer korrelierten Unterabfrage aus, siehe z.B:
</archiv/2006/7/t133015/#m861544>
</archiv/2008/1/t165377/#m1078290>
Vielen Dank für deine Antwort damit hätte ich es theoretisch geschafft! Nur nicht praktisch, da warte ich seit 30 Minuten oder so auf das Ergebnis, wobei die Tabelle nur 300 Einträge hat!
Die von mir genannte Abfrage ist leider komplizierter als die in deinen Links genannte. Die Abfrage, die die Daten in meinem Screenshot produziert sieht so aus (abgesehen von der delta-Spalte):
SELECT
t.topic_textID,
prev.topic_textID AS prev,
prev.level_order AS prev_order,
next.topic_textID AS next,
next.level_order AS next_order,
FROM temp_topics AS t
LEFT JOIN temp_topics AS prev ON t.level = prev.level AND prev.level_order < t.level_order
LEFT JOIN temp_topics AS next ON t.level = next.level AND next.level_order > t.level_order
WHERE t.level != ''
ORDER BY topic_textID, prev_order DESC, next_order ASC
Was diese Abfrage tut ist einfach erklärt: Die Tabelle temp_topics ist so aufgebaut:
CREATE TABLE IF NOT EXISTS temp_topics(
topic_textID VARCHAR(20) PRIMARY KEY,
title VARCHAR(200),
parent VARCHAR(20),
level VARCHAR(20),
level_order INTEGER,
print_group VARCHAR(20)
);
Anmerkung: Das sind Rohdaten, deswgen VARCHAR. Doch genau aus diesen mag ich ein vernünfiges verkettetes Modell machen. Es existiert eine Tabelle mit Zuordnungen zwischen topic_textID und einem Integer-Wert die ich verwenden werde wenn alles geht. Zusätzlich gibt es auch einen INDEX über level und level_order, also die Spalten die abgefragt werden.
Die Daten sind also in Gruppen ("level") aufgeteilt und die Sortierung innerhalb eines levels ist durch "level_order" bestimme. Diese Daten möchte ich nun in eine "Adjazenz"-Darstellung bringen.
Wie du erkennen kannst, muss ich hier prev_level und next_level kombiniert abfragen. D.h. in die WHERE-Klausel muss bei mir die ganze Abfrage noch einmal :-(
SELECT
t.topic_textID,
prev.topic_textID AS prev,
prev.level_order AS prev_order,
next.topic_textID AS next,
next.level_order AS next_order
FROM temp_topics AS t
LEFT JOIN temp_topics AS prev ON t.level = prev.level AND prev.level_order < t.level_order
LEFT JOIN temp_topics AS next ON t.level = next.level AND next.level_order > t.level_order
WHERE t.level != ''
AND prev.level_order = (
SELECT MAX(prev_sub1.level_order)
FROM temp_topics AS t_sub1
LEFT JOIN temp_topics AS prev_sub1 ON t_sub1.level = prev_sub1.level AND prev_sub1.level_order < t_sub1.level_order
LEFT JOIN temp_topics AS next_sub1 ON t_sub1.level = next_sub1.level AND next_sub1.level_order > t_sub1.level_order
WHERE t_sub1.topic_textID = t.topic_textID
GROUP BY t_sub1.topic_textID
)
AND next.level_order = (
SELECT MIN(next_sub2.level_order)
FROM temp_topics AS t_sub2
LEFT JOIN temp_topics AS prev_sub2 ON t_sub2.level = prev_sub2.level AND prev_sub2.level_order < t_sub2.level_order
LEFT JOIN temp_topics AS next_sub2 ON t_sub2.level = next_sub2.level AND next_sub2.level_order > t_sub2.level_order
WHERE t_sub2.topic_textID = t.topic_textID
GROUP BY t_sub2.topic_textID
)
ORDER BY topic_textID, prev_order DESC, next_order ASC
Gut, das funktioniert mal - Danke :-), braucht aber dennoch 40 Sekunden für nur 600 Datensätze in temp_topics.
Jetzt besteht aber das Problem dass nur die Einträge ausgegeben werden, die *beide* Nachbarn haben. Das jeweils erste und letzte Element eines "levels" wird aber nicht ausgegeben, da hier ja der Wert NULL ist.
Und jetzt wirds komisch: Ich frage einfach zusätzlich mit OR auf einen NULL Wert ab:
SELECT
t.topic_textID,
prev.topic_textID AS prev,
prev.level_order AS prev_order,
next.topic_textID AS next,
next.level_order AS next_order
FROM temp_topics AS t
LEFT JOIN temp_topics AS prev ON t.level = prev.level AND prev.level_order < t.level_order
LEFT JOIN temp_topics AS next ON t.level = next.level AND next.level_order > t.level_order
WHERE t.level != ''
AND (ISNULL(prev.level_order) OR prev.level_order = (
SELECT MAX(prev_sub1.level_order)
FROM temp_topics AS t_sub1
LEFT JOIN temp_topics AS prev_sub1 ON t_sub1.level = prev_sub1.level AND prev_sub1.level_order < t_sub1.level_order
LEFT JOIN temp_topics AS next_sub1 ON t_sub1.level = next_sub1.level AND next_sub1.level_order > t_sub1.level_order
WHERE t_sub1.topic_textID = t.topic_textID
GROUP BY t_sub1.topic_textID
))
AND (ISNULL(next.level_order) OR next.level_order = (
SELECT MIN(next_sub2.level_order)
FROM temp_topics AS t_sub2
LEFT JOIN temp_topics AS prev_sub2 ON t_sub2.level = prev_sub2.level AND prev_sub2.level_order < t_sub2.level_order
LEFT JOIN temp_topics AS next_sub2 ON t_sub2.level = next_sub2.level AND next_sub2.level_order > t_sub2.level_order
WHERE t_sub2.topic_textID = t.topic_textID
GROUP BY t_sub2.topic_textID
))
ORDER BY topic_textID, prev_order DESC, next_order ASC
Und nun braucht die Abfrage schon 30 Minuten natürlich mit maximaler CPU Last. Und das nur wegen der ISNULL Abfrage :-(
Hast du eine Ahnung wie man das beschleunigen könnte? Und wieso das so langsam ist?
Die Echtdaten haben dann 20000 Einträge und das ganze muss unter 5 Minuten ablaufen... :-/
Danke vielmals und lg, Peter