Rene123: MySQL Abfrage - Kategorien

Hallo,

habe eine MySQL Tabelle "cats" mit folgende Felder: id, name, subid. Und eine Tabelle "article" mit den Feldern: id, name, cat_id, description

Ich möchte nun wenn man eine Kategorie anklickt, das alle Artikel abgerufen werden inkl. aller Unterkategorien. Weiß aber nicht wirklich wie ich das lösen soll. Habe folgende Abfrage bisher:

$sql = "SELECT article.name as name FROM `article` JOIN `cats` ON ((cats.id='".$_GET["cat"]."' OR cats.subid='".$_GET["cat"]."') AND article.cat_id=cats.id);";	

Diese nimmt bisher aber nur 1 Unterkategorie. Wie löse ist das Problem? Gruß

  1. Hallo Rene123,

    Du solltest unter keinen Umständen get-Parameter direkt in den SQL-Code schreiben. (SQL-injection)

    Bis demnächst
    Matthias

    --
    Rosen sind rot.
    1. Danke ich weiß, bin auch noch nicht fertig. Mir geht es erstmal um die Abfrage wie ich alle Artikel inkl. Unterkategorien auflisten kann :). Trotzdem Danke für den Hinweis =)

  2. Hello,

    kannst Du mal bitte eine Skizze (ASCII-Grafik) von der geplanten Kategoriestruktur posten? Ich ahne da nämlich versteckten Aufwand...

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
  3. Hi,

    habe eine MySQL Tabelle "cats" mit folgende Felder: id, name, subid. Und eine Tabelle "article" mit den Feldern: id, name, cat_id, description

    Diese nimmt bisher aber nur 1 Unterkategorie. Wie löse ist das Problem?

    d.h. auch eine Subkategorie kann wieder Subsubkategorien und diese wieder Subsubsubkategorien usw. enthalten?

    Dann wäre evtl. "Nested Set" für die Kategorien sinnvoller als eine reine Parent-Verknüpfung. Ist zwar mehr Aufwand bei der Pflege der Kategorien, dafür aber deutlich einfacher, alle Artikel zu einer Kategorie samt aller Sub-Kategorien zu bekommen.

    cu,
    Andreas a/k/a MudGuard

  4. Hallo Rene123,

    bei deinem Datenmodell wäre die Lösung dafür eine rekursive Common Table Expression.

    MySQL ist da etwas langsam in der Umsetzung, diese Funktion gibt es in anderen DB seit Jahren und in MySQL seit April '17 (Version 8.0.1). Welche MYSQL Version verwendest Du?

    Ohne rekursive CTE geht es nicht in einer Query, da musst Du die Subkategorien von Hand einsammeln. Je nach Umfang deines Kategorienbaumes könnte es in dem Fall am billigsten sein, die Cat-Tabelle komplett einzulesen und die Subkategorien ohne weitere SQL Abfrage mit PHP zusammen zu suchen. Die Liste der gefundenen Kategorie-IDs klemmst Du dann in einen IN Ausdruck.

    Nested Sets sind eine gute Alternative, aber das muss man meines Wissens von Hand bauen.

    Rolf

    --
    sumpsi - posui - clusi
    1. Tach!

      Nested Sets sind eine gute Alternative, aber das muss man meines Wissens von Hand bauen.

      Man muss beim Einfügen nur Platz schaffen, indem man die L- und R-Werte, die größer als der R-Wert des Elternknoten sind, um zwei erhöht. Das lässt sich mit zwei Querys problemlos erledigen. Beim Löschen geht man adäquat vor. Den ganzen Vorgang in eine Tabellensperre oder Transaktion einbetten, damit keine Abfragen dazwischengrätschen.

      dedlfix.

    2. Hello,

      alternativ kann man aber auch bewusst denormalisieren, wenn man sich auf eine maximale Kategorietiefe beschränken mag. Dann sind die Selects absolut schnell. Nur Inserts können etwas länger dauern, weil man ggf. vorher erst eine Lücke im Nummernkreis schaffen muss.

      Diese Aufgaben kann man aber gut an stored Routines delegieren, sodass man dann von außen wieder nur Funktionen, wie my_insert(, my_delete, my_update, my_select) aufrufen muss. Hat zwei weitere Vorteile: man kann den Direktzugriff auf die Tabellen entziehen und man kann eine Select-Historie schreiben (wer's braucht).

      Liebe Grüße
      Tom S.

      --
      Es gibt nichts Gutes, außer man tut es!
      Das Leben selbst ist der Sinn.
  5. Eine kleine Anmerkung:

    habe eine MySQL Tabelle "cats" mit folgende Felder: id, name, subid. Und eine Tabelle "article" mit den Feldern: id, name, cat_id, description

    Was machst Du, wenn es zu einer Kategorie mehrere Unterkategorien gibt bzw. weitere Unterkategorien sukzessive hinzukommen? Du hast nur ein Feld und damit hast Du ein Problem. Lösung: Im Subrecord ein Feld parent also die Beziehng genau andersherum abspeichern.

    Vorausgesetzt natürlich, daß eine Unterkategorie nicht mehrere Elternkategorien hat. Da hast Du es beim Einfügen neuer Kategorien viel einfacher weil der Parent ja im Record selbst notiert ist. Dasselbe gilt ja dann auch sinngemäß für die Artikel. Und bei der Abfrage ergibt sich jeweils ein Array für die Artikel einer Kategorie bzw. für die Unterkategorien.

    Wäre zu Überlegen. MfG

    1. Danke für eure Antworten an euch alle!

      Ich teste dann mal was aus :-)

    2. Hallo pl,

      Was machst Du, wenn es zu einer Kategorie mehrere Unterkategorien gibt bzw. weitere Unterkategorien sukzessive hinzukommen? Du hast nur ein Feld und damit hast Du ein Problem. Lösung: Im Subrecord ein Feld parent also die Beziehng genau andersherum abspeichern.

      Vorausgesetzt natürlich, daß eine Unterkategorie nicht mehrere Elternkategorien hat.

      Muuuh - diesen Designbug hab ich überhaupt nicht beachtet...

      Deine Voraussetzung sollte selbstredend erfüllt sein. Es sei denn, irgendwer hat die Bedeutung von "unter" und "ober" umgedreht.

      Wenn Kategorien und Unterkategorien sich nicht 1:n verhalten, ist eh Ende mit einzelnen Tabellen oder Nested Sets, dann hilft nur noch die gute alte m:n Beziehungstabelle.

      Rolf

      --
      sumpsi - posui - clusi