dedlfix: Array mit Nested Set Werten zu Html-Liste/Menu verarbeiten

Beitrag lesen

Tach!

|leftKey | rightKey | menu_id | page_id |

| 0      | 1        | 1       | 1       |

| 2      | 3        | 1       | 2       |

| 0      | 1        | 2       | 1       |

Das Statement zu ändern ist kein Problem, nur an die DB komme ich nicht so einfach ran.
Ich wollte das Statement nur nicht ändern aus Angst etwas kaputt zu machen.

Das ist schon kaputt und jemand hat es durch die Gruppierung zu reparieren versucht. Mal abgesehen von den Rechten liefert dir dieser Teil

SELECT cms\_pages.id
  FROM cms\_menu\_pages
  JOIN cms\_pages
  ON cms\_menu\_pages.page\_id = cms\_pages.id
  WHERE cms\_menu\_pages.menu\_id = ?

oder einfacher

SELECT cms\_menu\_pages.page\_id
  FROM cms\_menu\_pages
  WHERE cms\_menu\_pages.menu\_id = ?

alle Pages zu einer Menu-ID. Bei Menu-ID 1 und obigen Daten bekommst du also Page 1 und 2. Wenn beide Seiten in Content enthalten sind, liefert das SELECT cms\_content.page\_id FROM cms\_content wieder beide Page-IDs an die nun ganz äußere Query. Und wenn du da Menu-Pages mit diesen beiden Page-IDs befragst, bekommst du Menu 1 _und_ 2 - obwohl du in der Unterabfrage nur nach 1 gefragt hast.

Das heißt also, dass du für die Page-ID 1 topnavi und footernavi geliefert bekommst. Das gruppierst du und erhältst zufällig einen von beiden Werten. (MySQL trifft keine Aussage, welchen von den möglichen Werten es nimmt. Das kann zufällig immer der gewünschte sein, aber verlassen kann man sich nicht darauf.) Und das halte ich für einen Fehler. Die Gruppierung sollte weg und stattdessen die äußere Query um die Bedingung "AND cms\_menu\_pages.menu\_id=?" erweitert werden.

Nested-Sets-Abfragen verwenden oftmals Self-Joins und Gruppierung, so auch die Level-Query. Das mit der jetzigen gejointen und bereits gruppierten Query zu verheiraten wird eine ganz schöne Herausforderung werden.

Bei der Komplexität der Query wird es wohl auf eine Array-Lösung hinauslaufen. Andererseits kann man die Komplexität mit noch mehr Komplexität augenscheinlich verringern. Die ungetestete Idee wäre, die Query in eine View zu bringen, dann wird die Anwendung des Self-Joins und der Gruppierung einfacher, als wenn man das Riesending doppelt notieren muss.
Tut mir leid, ich kann dir nicht ganz folgen. "in eine View bringen"? Und wieso doppelt?

Eine View ist, wenn man ein (umfangreiches) SELECT-Statement in einem CREATE-VIEW-Statement kapselt. Man sagt dann nur noch SELECT viewname und gegebenenfalls WHERE-Bedingungen dazu. Dummerweise kannst du das mit der View in dem Fall gleich wieder vergessen, denn die View ist leider keine Funktion, der man Parameter übergeben kann, die dann an bliebiger Stelle des inneren Statements verwendet werden könnten. Eine Stored Procedure könnte das, die kann man aber nicht so flexibel einsetzen wie eine Tabelle oder View, sondern immer nur einzelstehend. Für den oben erwähnten SELF-Join (der notwendig ist, um das Level zu erhalten) braucht es aber eine doppelte Verwendung. Ich nehme an, dass eine View zweimal im FROM angegeben werden kann (wie Tabellen auch), und bin mir sicher, dass das für CALL nicht geht (das geht gar nicht als Subquery zu verwenden).

Damit ändern sich die Lösungsmöglichkeiten erheblich. Wenn das jetzige SELECT-Statement (abgesehen von den Fehlerkorrekturen) unverändert bleiben soll, bringt es hier nichts, es nur in eine Stored Procedure zu kapseln. Eine SP kann aber trotzdem helfen. Das SELECT-Statement muss sein Ergebnis in einer temporären Tabelle ablegen und die kann man dann in einem weiteren SELECT-Statement selfjoinen (alles innerhalb der SP).

Eine andere Idee ist, das jetzige verschachtelte SELECT zumindest soweit zu entschachteln (und einfache JOINS draus zu machen), dass die Parameter als Bedingungen des außeren Statements formuliert werden können. Dann kann man das Statement (abzüglich der Bedingungen) in einer View ablegen, und die lässt sich dann syntaktisch gesehen relativ einfach selfjoinen.

dedlfix.