我打算在php中创建一个多选下拉列表或多选复选框表单元素。但是与父子菜单项关系发货。
Ex:所以我有三个单独的表tbl_branch,tbl_area,tbl_region和另外两个表用于映射tbl_regiontoarea和tbl_areatobranch。现在我需要一个多选或多选复选框,它看起来像这样:
Branch 1
Area 1
Region 1
Region 2
Area 2
Region 3
Region 4
Region 7
Region 9
Area 5
Area 7
Region 8
Branch 2
Area 3
Branch 3
Branch 4
Branch 5
Area 6
Region 10
Area 2
正如您猜测的那样,分支是层次结构中最顶层的,区域是最低层,即分支是父级。我希望它循环直到它找到它的孩子。一旦它停止找到任何子项,它将转移到数组中的下一个父项。
我对数组非常糟糕,并且形成了复杂的SQL查询,因此期待在如何做到这一点上有一些起步方向。如果有人能帮助我,我真的很感激。
提前致谢
答案 0 :(得分:4)
我建议你给这个读一读
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
我已经建立了一个几乎相同数据的树,并使用上述文档中建议的方法使问题变得更加简单,特别是在确定父母和兄弟姐妹达到n级时。
简短版本是您在每个节点的“左”和“右”分配一个数字,然后使用它可以非常有效地选择树的片段。在这篇文章中,更长时间的卷曲版本,并且比我更彻底地解释它并且包括有用的MySQL代码。
这是主表的潜在大纲
treeTable (
// ID field
id INT UNSIGNED PK AI,
// Fields for branching
lft INT UNSIGNED,
rgt INT UNSIGNED,
// ID fields for the specific types
leafType ENUM('Branch','Area','Region'),
leafID INT UNSIGNED,
leafName VARCHAR
)
UNIQUE INDEX (leafType,leafID)
如果您需要每种类型的特定数据,那么您可以为它们创建单独的表,但上面的内容可以让您创建树,映射id并允许关系与显示名称一起存储。
当然,每个leafType之间可以规范化的数据越多越好,理想情况下,它们实际上都是相同类型的数据,因为它们都是地理分段
以您的数据样本为例
Branch 3
Branch 4
Branch 5
Area 6
Region 10
Area 2
你最终会得到像
这样的表格id lft rgt leafType leafID
1 1 2 'Branch' 3
2 3 4 'Branch' 4
3 5 12 'Branch' 5
4 6 9 'Area' 6
5 7 8 'Region' 10
6 10 11 'Area' 2
可以在链接文章中找到有关如何插入等的查询,即(从http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/逐字引用)
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft FROM nested_category
WHERE name = '2 WAY RADIOS';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft;
INSERT INTO nested_category(name, lft, rgt) VALUES('FRS', @myLeft + 1, @myLeft + 2);
UNLOCK TABLES;
然后SELECT可以说明树(再次从源中逐字逐句)
SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;
上面2中的字段/表名当然没有变化,但您可以根据需要更新表/字段名称
根据我的最新评论,下面是我用于插入新行的存储过程的定义
CREATE PROCEDURE `addOptionalExtraToTree`(inParentOptionID INT,inOptionName VARCHAR(40),inLeafType VARCHAR(20))
BEGIN
DECLARE myRight INT UNSIGNED DEFAULT 0;
SELECT optionalExtra_tree_right-1
INTO myRight
FROM optionalExtras
WHERE optionalExtraID = inParentOptionID;
IF myRight = 0 THEN
SELECT COALESCE(MAX(optionalExtra_tree_right),0)
INTO myRight
FROM optionalExtras;
END IF;
UPDATE optionalExtras
SET optionalExtra_tree_right = optionalExtra_tree_right + 2
WHERE optionalExtra_tree_right > myRight;
UPDATE optionalExtras
SET optionalExtra_tree_left = optionalExtra_tree_left + 2
WHERE optionalExtra_tree_left > myRight;
INSERT INTO optionalExtras (
optionalExtra_name,
optionalExtra_leaf_type,
optionalExtra_tree_left,
optionalExtra_tree_right
) VALUES (
inOptionName,
inLeafType,
myRight + 1,
myRight + 2
);
SELECT LAST_INSERT_ID() AS optionalExtraID;
END;
然后使用以下
之类的调用调用它CALL addOptionalExtraToTree(0,'New root option','Region');
CALL addOptionalExtraToTree(4,'New child option','Area');