2016-04-19 4 views
0

У меня есть три таблицы. Одна таблица называется places, эта таблица имеет разные места (например, предприятия, рестораны и т. Д.), Каждое «место» связано с таблицей categories, однако некоторые категории имеют подкатегории в иерархической структуре (например, Thai Food - это подкатегории ресторанов). Эта система позволяет администратору создавать места и сопоставлять их с соответствующей категорией или подкатегорией.Получение категорий и подкатегорий, связанных из таблиц Mysql

Что я хотел бы знать, так это лучший способ получить эти отношения? В настоящее время я использую JOINs и GROUP_CONCAT, но я все еще не получаю хороший набор результатов.

Это мои таблицы:

мест:

+----+----------------+ 
| 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   | 
+----------+-------------+ 

категории:

Как вы можете видеть, некоторые места прикреплены к подкатегории, некоторые места прикрепляются непосредственно к родительской категории (без подкатегорий), а некоторые места имеют несколько подкатегорий, которые имеют разные родительские категории.

Чтобы получить мои результаты, я попытался следующий 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` 

Но мои результаты придумали некоторые категории создаются как подкатегория или наоборот.

То, что я хотел бы, чтобы иметь некоторый тип результирующего набора, который позволил бы мне что-то вроде этого:

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 

В идеале, все это будет создано так, что я могу входные фильтры. Например, если я только хочу видеть места с категорией ресторанов или местами с правительством и подкатегорией итальянской кухни ...

Может кто-нибудь, пожалуйста, помогите мне понять это?

+0

Вы можете получить всю категорию с подкатегорией в рекурсивном виде. Проверьте этот .http: //thecoderain.blogspot.in/2016/03/get-category-and-subcategory-tree-in.html – shubham715

ответ

2

До тех пор, пока у вас есть только два уровня категории (например, нет вложенных подкатегорий), затем с помощью JOIN может быть хорошо.

Проблема в том, что ваши данные иногда ссылаются на родительские категории и иногда ссылаются на подкатегории. Вот почему вы получаете смешанные результаты.

Чтобы избежать смешанные результаты, вы можете использовать что-то вроде этого:

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` 

я не уверен, что это очень эффективный вариант, но как вы можете видеть, что вам нужно, чтобы отделить «связанные категории, являются родителями "(c_direct_parent), а" родственными категориями являются дети "(c_child).

С этим разделением вы можете теперь правильно получить список данных для родителей и детей. Для ясности я помещаю «...» для внутренних элементов GROUP_CONCAT.

1

Так не совсем хороший способ, но это может быть достаточно ваше porblem решение

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 

Выход: -

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

Теперь вам нужно подумать, как вы можете группироваться по имени.

Обходной путь для этого, если партитус пуст, замените его на пустую строку иначе с именем parentCategory.

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` 

производство выход как

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

Смежные вопросы