获取从Mysql表

时间:2016-04-19 04:01:39

标签: php mysql sql

我有三张桌子。一个表叫做places,这个表包含不同的地方(例如商家,餐馆等......)每个地方"地点"链接到一个名为categories的表,但是某些类别具有分层结构的子类别(即泰国食品是餐馆的子类别)。该系统允许管理员创建场所并将其与相应的类别或子类别进行匹配。

我想知道的是获得这些关系的最佳方式是什么?目前我正在使用JOIN和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           |
+----------+-------------+

类别

+----+-----------+------------+
| id | parent_id | name       |
+----+-----------+------------+
| 1  | null      | Restaurant |
+----+-----------+------------+
| 2  | 1         | Thai Food  |
+----+-----------+------------+
| 3  | 1         | Italian    |
+----+-----------+------------+
| 4  | null      | Government |
+----+-----------+------------+
| 5  | 4         | Library    |
+----+-----------+------------+
| 6  | 4         | Military   |
+----+-----------+------------+

正如您所看到的,某些地方附加到子类别,有些地方直接附加到父类别(没有子类别),有些地方有多个子类别,这些子类别具有不同的父类别。

为了获得我的结果,我尝试了以下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

理想情况下,这将全部创建,以便我可以输入过滤器。例如,如果我只想看到有餐馆类别的地方,或者有意大利食品的政府和子类别的地方......

有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

只要你只有两个级别的类别(例如没有子子类别),那么使用JOIN就可以了。

问题是,您的数据有时会引用父类别,有时会引用子类别。这就是为什么你的结果好坏参与。

为避免混合结果,您可以使用以下内容:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="ApiController as ApiCtrl">
    {{ApiCtrl.Api.status}} {{ApiCtrl.Api.meta.count}} {{ApiCtrl.Api.data[0].nickname}} {{ApiCtrl.Api.data[0].account_id}}
  </div>

  <hr>

  <div ng-controller="ApiController as ApiCtrl">
    <div>
      <table>
        <thead>
          <tr>
            <th ng-repeat="(key, value) in ApiCtrl.Api">{{key}}</th>
          </tr>
        </thead>
        <tbody>
          <td ng-repeat="(key, value) in ApiCtrl.Api">
            {{value}}
          </td>
        </tbody>
      </table>
    </div>
  </div>
</div>

我不确定这是一个非常有效的选项,但正如您所看到的,您需要将“相关类别作为父母”(c_direct_parent)和“相关类别是儿童”(c_child)分开。

通过这种分离,您现在可以正确检索父母和孩子的数据列表。为清楚起见,我将“...”放入GROUP_CONCAT内部。

答案 1 :(得分:1)

所以这不是一个好方法,但这可能足以让你的问题解决方案

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

现在你必须考虑如何按名称分组。

对此的解决方法是,如果parenty为空,则将其替换为空白字符串,否则使用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`

生成输出

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