Andreas N.: Kind Elemente in einer Hierarchie/Baumstruktur

Hallo,

es geht um die Abbildung einer Hierarchie/Baumstruktur in einer mysql Datenbank.

Tabelle object:
-------------
| id        |
| name      |
| parent_id |
-------------

Nun möchte ich zu einer id auch alle Kind Einträge ermitteln, um mir alle zugehörigen objekt Namen zu einer id ausgeben zu lassen.

Zum Beispiel:

SELECT
 object.name
FROM
 object
WHERE
 object.id IN (Liste-mit-allen-kind-objekten-zu-einer-id)

Um nun alle Kind-Objekte zu einer Objekt-id (im SQL: "Liste-mit-allen-kind-objekten-zu-einer-id") zu erhalten müsste ich diese ids ermitteln. Das ist ja weiter kein Problem. Jedoch enthält die object Tabelle ca. 280.000 Einträge, was das SQL-Statement -für den Fall, dass ein Objekt aus einer der obersten Ebene ausgewählt wird- sehr lang und wahrscheinlich auch nicht gerade performant macht.

Meine Idee ist es nun eine weitere Tabelle anzulegen, in der zu einem object (object_id) alle Kindelemente (object_child_id) aufgelistet werden:

child2object
--------------------
| object_id        |
| object_child_id  |
--------------------

object_id und object_child_id wären dann der Primär-Schlüssel.

Das Statement würde dann so aussehen:

SELECT
 object.name
FROM
 object
INNER JOIN
 child2object
ON
 (object.id = child2object.object_child_id)

WHERE child2object.object_id = 'irgendeine-id'

Bei 280.000 Einträgen in der objekt Tabelle wird die child2object Tabelle natürlich auch nicht gerade klein.

Ist das eine gute Lösung oder gibt es bessere Ansätze?

Vielen Dank für Hilfe & viele Grüße
Andreas

  1. Sup!

    Tabelle object:

    | id        |
    | name      |

    parent_id

    Warum schreibst Du eigentlich nicht

    SELECT object.name
    FROM object
    WHERE parent_id = id;

    ?!?

    Irgendwelche Daten zu duplizieren halte ich auf jeden Fall für eine ziemlich dumme Idee...

    Gruesse,

    Bio

    --
    Keep your friends close, but your enemies closer!
    1. Hallo Bio,

      Tabelle object:

      | id        |
      | name      |

      parent_id

      Warum schreibst Du eigentlich nicht

      SELECT object.name
      FROM object
      WHERE parent_id = id;

      ich verstehe nicht so ganz was Du meinst. Denn mit dem SQL Statement erhalte ich nicht die gewünschte Ausgabe (genau genommen gar keine Datensätze ;-) oder ich habe etwas übersehen?

      Vielleicht habe ich mich in meinem ersten Posting etwas ungenau ausgedrückt. Ich möchte alle Kind Elemente erhalten, also auch die Kindes Kinder und wiederum deren Kinder usw.

      In der Tabelle object ist die 'id' der Primärschlüssel, 'name' ein beliebiger Name und 'parent_id' zeigt wieder auf die 'id'.

      Beispiel Daten für die object Tabelle:

      | id | name | parent_id |
      -------------------------
      |  1 | a    |    0      |
      |  2 | b    |    0      |
      |  3 | aa   |    1      |
      |  4 | aaa  |    3      |
      |  5 | aaaa |    4      |
      |  6 | bb   |    2      |
      |  7 | bbb  |    6      |

      Für die id=1 wären es die Datensätze:

      | id | name | parent_id |
      -------------------------
      |  3 | aa   |    1      |
      |  4 | aaa  |    3      |
      |  5 | aaaa |    4      |

      Also die ids 3, 4 und 5. So würde das Statement um die Namen aller Kinder (und Kindes Kinder) zu ermitteln wie folgt aussehen:

      SELECT
       object.name
      FROM
       object
      WHERE
       object.id IN (3,4,5)

      Dies liefert mir die gewünschten Namen "aa","aaa" und "aaaa".

      Diese Liste mit allen Kindern kann ich natürlich serverseitig ermitteln, doch bei relativ vielen Datensätzen (ca. 280.000) wie in meinem Fall würde im Statement der 'IN (x,y,z)'-Teil sehr groß werden.

      Die Idee ist dies mit Hilfe einer zweiten Tabelle und dem entsprechendem JOIN zu verhindern.

      Viele Grüße
      Andreas

  2. Hallo,

    object.id IN (Liste-mit-allen-kind-objekten-zu-einer-id)

    Um nun alle Kind-Objekte zu einer Objekt-id (im SQL: "Liste-mit-allen-kind-objekten-zu-einer-id") zu erhalten müsste ich diese ids ermitteln.

    Ich habe eine weitere Lösung gefunden, die mir sinnvoller erscheint und die Lösung des Problems erleichtert. Anstatt des Zeigermodells (über die 'parent_id') ist die Verwendung des Mengenmodells eine bessere Alternative. Streng genommen gibt es hier wegen der zusätzlichen left und right Spalten auch wieder Redundanz, doch die Lösung gefällt mir besser als eine weiteren Tabelle anzulegen.

    Eine gute Einführung hierzu gibt es unter http://kris.koehntopp.de/artikel/sql-self-references/.

    Grüße
    Andreas

    1. Sup!

      Wohl dem, der eine Codasyl-Datenbank irgendwo ausgraben kann... da war dieser Mechanismus Standard.

      Gruesse,

      Bio

      --
      Keep your friends close, but your enemies closer!