2016-04-19 13 views
0

Ich habe drei Tabellen. Eine Tabelle heißt places, diese Tabelle enthält verschiedene Orte (wie Geschäfte, Restaurants, etc ...) Jeder "Ort" ist mit einer Tabelle namens categories verknüpft, jedoch haben einige Kategorien Unterkategorien in einer hierarchischen Struktur (dh Thai Food ist ein Unterkategorie Restaurants). Mit diesem System kann ein Administrator Orte erstellen und sie mit einer entsprechenden Kategorie oder Unterkategorie abgleichen.Abrufen von Kategorien und Unterkategorien aus Mysql-Tabellen

Was würde ich gerne wissen, was ist der beste Weg, um diese Beziehungen zu erhalten? Derzeit verwende ich JOINs und GROUP_CONCAT, aber ich bekomme immer noch keine gute Ergebnismenge.

Das sind meine Tabellen:

Plätze:

+----+----------------+ 
| id | name   | 
+----+----------------+ 
| 1 | Mings Place | 
+----+----------------+ 
| 2 | Halsey Library | 
+----+----------------+ 
| 3 | Stellas USO | 
+----+----------------+ 

places_categories_rel:

+----------+-------------+ 
| place_id | category_id | 
+----------+-------------+ 
| 1  | 2   | 
+----------+-------------+ 
| 2  | 4   | 
+----------+-------------+ 
| 3  | 3   | 
+----------+-------------+ 
| 3  | 4   | 
+----------+-------------+ 

Kategorien:

Wie Sie sehen können, sind einige Orte an eine Unterkategorie angehängt, einige Orte sind direkt an eine Elternkategorie angehängt (ohne Unterkategorien), und einige Orte haben mehrere Unterkategorien, die unterschiedliche Elternkategorien haben.

meine Ergebnisse zu erhalten, habe ich versucht die folgende SQL:

'SELECT `p`.*, 
     GROUP_CONCAT(DISTINCT(CONCAT (ca.id, "|", `ca`.`parent_id`, "|", ca.name))) as subcategories, 
     GROUP_CONCAT(DISTINCT(CONCAT (ca1.id, "|", `ca1`.`parent_id`, "|", ca1.name))) as categories 
FROM `places` `p` 
LEFT JOIN `places_categories_rel` `rel` ON `rel`.`place_id`=`p`.`id` 
LEFT JOIN `categories` `ca` ON `ca`.`id`=`rel`.`category_id` 
LEFT JOIN `categories` `ca1` ON `ca1`.`id`=`ca`.`parent_id` 
GROUP BY `p`.`id` 

Aber meine Ergebnisse kommen mit einigen Kategorien Unterkategorien oder umgekehrt eingestellt wird.

Was ich möchte, ist irgendeine Art von Ergebnismenge zu haben, die mir so etwas zu haben erlauben würde:

array (size=3) 
    0 => 
    array (size=2) 
     'name' => string 'Mings Place' (length=11) 
     'categories' => 
     array (size=1) 
      0 => 
      array (size=2) 
       'name' => string 'Restaurant' (length=10) 
       'subcategories' => 
       array (size=1) 
        0 => string 'Thai Food' (length=9) 
    1 => 
    array (size=2) 
     'name' => string 'Halsey Library' (length=14) 
     'categories' => 
     array (size=1) 
      0 => 
      array (size=2) 
       'name' => string 'Government' (length=10) 
       'subcategories' => 
       array (size=1) 
        0 => string 'Library' (length=7) 
    2 => 
    array (size=2) 
     'name' => string 'Stellas' (length=7) 
     'categories' => 
     array (size=2) 
      0 => 
      array (size=2) 
       'name' => string 'Restaurant' (length=10) 
       'subcategories' => 
       array (size=1) 
        0 => string 'Library' (length=7) 
      1 => 
      array (size=2) 
       'name' => string 'Government' (length=10) 
       'subcategories' => null 

Idealerweise wird dies alles geschaffen werden, damit ich kann Eingangsfilter. Zum Beispiel, wenn ich nur Orte mit Kategorie von Restaurants sehen möchte, oder Orte mit Regierung und Unterkategorie von italienischem Essen ...

Kann mir bitte jemand helfen, das herauszufinden?

+0

Sie können alle Kategorien mit Unterkategorien auf rekursive Weise erhalten. Überprüfen Sie diese .http: //thecoderain.blogspot.in/2016/03/get-category-and-subcategory-tree-in.html – shubham715

Antwort

2

Solange Sie nur zwei Ebenen von Kategorien (zB keine Unter Unterkategorien), dann mit einem JOIN kann gut sein.

Das Problem besteht darin, dass Ihre Daten manchmal auf übergeordnete Kategorien verweisen und manchmal auf Unterkategorien verweisen. Deshalb erhalten Sie gemischte Ergebnisse.

gemischte Ergebnisse zu vermeiden, können Sie so etwas wie dieses verwenden:

SELECT 
    p.*, 
    CONCAT(IFNULL(GROUP_CONCAT(c_parent...), ''), ',', IFNULL(GROUP_CONCAT(c_direct_parent...), '')), 
    GROUP_CONCAT(c_child...), 
FROM `places` AS p 
    LEFT JOIN `places_categories_rel` AS rel 
    ON rel.`place_id` = p.`id` 
    LEFT JOIN `categories` AS c_direct_parent 
    ON c_direct_parent.`id` = rel.`category_id` 
    AND c_direct_parent.`parent_id` IS NULL 
    LEFT JOIN `categories` AS c_child 
    ON c_child.`id` = rel.`category_id` 
    AND c_child.`parent_id` IS NOT NULL 
    LEFT JOIN `categories` AS c_parent 
    ON c_parent.`id` = c_child.`parent_id` 
GROUP BY p.`id` 

Ich sehe eine sehr effiziente Möglichkeit, aber wie Sie können nicht sicher bin, das ist, müssen Sie „verbundenen Kategorien zu trennen, dass sind Eltern "(c_direct_parent) und" verwandte Kategorien sind Kinder "(c_child).

Mit dieser Trennung können Sie jetzt eine Liste von Daten für die Eltern und die Kinder ordnungsgemäß abrufen. Zur besseren Übersicht habe ich "..." für die GROUP_CONCAT-Interna angegeben.

1

Also nicht gerade ein guter Weg, aber dies könnte Ihre porblem Lösung

SELECT `p`.*,c.* 
FROM `places` `p` 
LEFT JOIN `places_categories_rel` `rel` ON `rel`.`place_id`=`p`.`id` 
LEFT JOIN (
SELECT c1.id as childID, c1.name ChildName, c2.name as ParentName 
from categories c1 
LEFT OUTER JOIN categories c2 
ON c1.parent_id = c2.id) c on c.childID= rel.category_id 

Ausgang genügen: -

id name childID ChildName ParentName
1 Mings Place 2 Thai Food Restaurant
3 Stellas 3 Italian Restaurant
2 Halsey Library 4 Government NULL
3 Stellas 4 Government NULL

Nun müssen Sie überlegen, wie Sie nach Namen gruppieren können.

Eine Problemumgehung dafür ist, wenn Parenty leer ist, ersetzen Sie es durch leere Zeichenfolge andernfalls mit ParentCategory-Name.

SELECT `p`.*,GROUP_CONCAT(ChildName) as Category,GROUP_CONCAT(if(ParentName IS NULL ," ",ParentName)) as parent 
FROM `places` `p` 
LEFT JOIN `places_categories_rel` `rel` ON `rel`.`place_id`=`p`.`id` 
LEFT JOIN (
SELECT c1.id as childID, c1.name ChildName, c2.name as ParentName 
from categories c1 
LEFT OUTER JOIN categories c2 
ON c1.parent_id = c2.id) c on c.childID= rel.category_id 
GROUP BY `p`.`id` 

Erzeugen von Ausgangs als

id name Category parent
1 Mings Place Thai Food Restaurant
2 Halsey Library Government
3 Stellas Italian,Government Restaurant,

Verwandte Themen