Mysql-在层次结构

时间:2016-11-29 16:32:18

标签: php mysql join relational-database

我有一个类别表,我将其解析为categories_to_categories关系的另一个表many-to-many。 现在我想只选择那些有

的类别
  1. parent_id = 0
  2. 他们的父母的parent_id = 0
  3. 这是我的Fiddle,在结果集中,我有两个问题,

    1. 结果重复
    2. 自定义衬衫类别不应该在那里,因为它已经有父母,而其父母没有parent_id =0
    3. DDL:

      CREATE TABLE `categories` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `uuid` varchar(25) DEFAULT NULL,
        `name` varchar(255) DEFAULT NULL,
        `description` text,
        `status` enum('ACTIVE','INACTIVE') DEFAULT 'ACTIVE',
        `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
        `banner_path` varchar(255) DEFAULT NULL,
        `franchise_id` int(11) DEFAULT NULL,
        PRIMARY KEY (`id`),
        UNIQUE KEY `categories_uuid_uindex` (`uuid`)
      );
      
      
      
      INSERT INTO `categories` VALUES (1,'xyz','Printing','test','ACTIVE','2016-11-29 13:54:15','2016-11-29 13:54:18',NULL,3),(2,'abc','Digital','test','ACTIVE','2016-11-29 14:33:48','2016-11-29 14:33:53',NULL,3),(3,'def','Video','test','ACTIVE','2016-11-29 14:34:25','2016-11-29 14:34:29',NULL,3),(4,'s','Merchandise printing','test','ACTIVE','2016-11-29 14:35:02','2016-11-29 14:35:04',NULL,3),(5,'4','D/C','test','ACTIVE','2016-11-29 14:35:24','2016-11-29 14:35:27',NULL,3),(6,'2','Goods','test','ACTIVE','2016-11-29 14:35:49','2016-11-29 14:35:51',NULL,3),(8,'5','B/A Templates','test','ACTIVE','2016-11-29 14:36:26','2016-11-29 14:36:28',NULL,3),(9,'gggg','Customized Shirts','test','ACTIVE','2016-11-29 14:37:00','2016-11-29 14:37:01',NULL,3);
      
      
      
      CREATE TABLE `categories_to_categories` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `category_id` int(11) DEFAULT NULL,
        `parent_id` int(11) DEFAULT NULL,
        `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
        PRIMARY KEY (`id`)
      );
      
      
      
      INSERT INTO `categories_to_categories` VALUES (1,1,0,'2016-11-29 13:54:56','2016-11-29 13:54:59'),(2,2,0,'2016-11-29 14:38:10','2016-11-29 14:38:17'),(3,3,0,'2016-11-29 14:38:28','2016-11-29 14:38:29'),(4,4,1,'2016-11-29 14:38:48','2016-11-29 14:38:51'),(5,5,2,'2016-11-29 14:39:28','2016-11-29 14:39:30'),(6,6,0,'2016-11-29 14:39:41','2016-11-29 14:39:43'),(7,4,6,'2016-11-29 14:39:52','2016-11-29 14:39:55'),(8,7,1,'2016-11-29 14:40:11','2016-11-29 14:40:17'),(9,8,4,'2016-11-29 14:40:29','2016-11-29 14:40:32'),(10,9,2,'2016-11-29 14:40:40','2016-11-29 14:40:42');
      

      查询无效:

      SELECT * 
        FROM CATEGORIES                     A
       INNER JOIN CATEGORIES_TO_CATEGORIES  B
        ON A.ID = B.ID
       AND B.PARENT_ID = 0
        OR (SELECT PARENT_ID
              FROM CATEGORIES_TO_CATEGORIES
             WHERE ID = B.PARENT_ID
           ) = 0 ;
      

1 个答案:

答案 0 :(得分:1)

可能的解决方案之一是使用根类别及其子类的联合:

SELECT c.id, c.name FROM categories c 
WHERE c.id IN (
  SELECT cc.category_id FROM categories_to_categories cc 
  WHERE cc.parent_id = 0 

  UNION

  SELECT pc.category_id FROM categories_to_categories cc 
  LEFT JOIN categories_to_categories pc ON cc.category_id = pc.parent_id 
  WHERE cc.parent_id = 0 
)
ORDER BY c.id;

此查询的结果将是没有重复的根类别/子类别列表('商品打印'是' Printing'' Goods'的子节点,但在结果集中它只出现一次):

+----+----------------------+
| id | name                 |
+----+----------------------+
|  1 | Printing             |
|  2 | Digital              |
|  3 | Video                |
|  4 | Merchandise printing |
|  5 | D/C                  |
|  6 | Goods                |
|  9 | Customized Shirts    |
+----+----------------------+