0

我想知道 mysql 中表的最佳结构是什么,该结构需要具有:

Parent (level 0)
  -region (inside regions are)(level 1)
     -countrys (inside countrys are)(level 2)
       -Districts (level 3)

所以我需要将所有这些信息存储在同一张表中,有什么线索吗?如果你需要知道我在 cakephp 上构建这个应用程序。

提前致谢。

4

1 回答 1

1

我冲动地为您的情况制作了一个 EER 图。
请告诉我它是否有效(如果您同意),我将等待您的反馈。

ER图

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

DROP SCHEMA IF EXISTS `hierarchy` ;
CREATE SCHEMA IF NOT EXISTS `hierarchy` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `hierarchy` ;

-- -----------------------------------------------------
-- Table `hierarchy`.`level`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `hierarchy`.`level` (
  `id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(20) NOT NULL ,
  PRIMARY KEY (`id`) ,
  UNIQUE INDEX `name_UNIQUE` (`name` ASC) )
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `hierarchy`.`location`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `hierarchy`.`location` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `parent` INT UNSIGNED NULL ,
  `name` VARCHAR(50) NOT NULL ,
  `level` TINYINT UNSIGNED NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_location_location_idx` (`parent` ASC) ,
  INDEX `fk_location_level1_idx` (`level` ASC) ,
  INDEX `index_name` (`name` ASC) ,
  CONSTRAINT `fk_location_location`
    FOREIGN KEY (`parent` )
    REFERENCES `hierarchy`.`location` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_location_level1`
    FOREIGN KEY (`level` )
    REFERENCES `hierarchy`.`level` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

USE `hierarchy` ;

-- -----------------------------------------------------
-- Placeholder table for view `hierarchy`.`details_location`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `hierarchy`.`details_location` (`location_id` INT, `location_name` INT, `parent_id` INT, `level_id` INT, `level_name` INT, `children` INT);

-- -----------------------------------------------------
-- View `hierarchy`.`details_location`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `hierarchy`.`details_location`;
USE `hierarchy`;
CREATE  OR REPLACE VIEW `hierarchy`.`details_location` AS
SELECT
  x.`id` AS `location_id`,
  x.`name` AS `location_name`,
  IFNULL(x.`parent`, 0) AS `parent_id`,
  y.`id` AS `level_id`,
  y.`name` AS `level_name`,
  (SELECT COUNT(*) FROM location AS l WHERE l.parent = x.id) AS `children`
FROM location AS `x`
INNER JOIN `level` AS `y`
  ON (x.`level` = y.id);
USE `hierarchy`;

DELIMITER $$
USE `hierarchy`$$

CREATE TRIGGER `insert_location` BEFORE INSERT ON location
FOR EACH ROW BEGIN
  DECLARE x INT UNSIGNED DEFAULT 1;

  IF NEW.parent IS NOT NULL THEN
    SELECT `level`+1 INTO x FROM location WHERE id = NEW.parent;
  END IF;

  SET NEW.`level` = x;
END$$

DELIMITER ;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

-- -----------------------------------------------------
-- Data for table `hierarchy`.`level`
-- -----------------------------------------------------
START TRANSACTION;
USE `hierarchy`;
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (1, 'parent');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (2, 'region');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (3, 'country');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (4, 'district');

COMMIT;

INSERT INTO location (parent,name,level) VALUES
(NULL,'a1',NULL), (NULL,'a2',NULL), (NULL,'a3',NULL);

INSERT INTO location (parent,name,level) VALUES
(1,'b1',NULL), (1,'b2',NULL), (2,'b3',NULL),
(2,'b4',NULL), (3,'b5',NULL), (3,'b6',NULL);

INSERT INTO location (parent,name,level) VALUES
(4,'c1',NULL), (4,'c2',NULL), (5,'c3',NULL),
(5,'c4',NULL), (6,'c5',NULL), (6,'c6',NULL),
(7,'c7',NULL), (7,'c8',NULL), (8,'c9',NULL),
(8,'c10',NULL), (9,'c11',NULL), (9,'c12',NULL);

SELECT * FROM details_location;

[(大部分)来自 MySQL Workbench 5.2 的自动生成代码]
请注意,触发器insert_location在注册时确定项目的级别,因此父级的级别增加一个单位。

于 2013-04-06T03:02:34.743 回答