15
मेरे पास क्लोजर टेबल विधि का उपयोग कर एक MySQL डेटाबेस पदानुक्रमित डेटा है। स्क्रिप्ट बनाने वाला एक सरल नमूना डेटाबेस प्रश्न का पालन करता है। इस समय मेरी समस्या यह है कि मैं सही क्रम में डेटाबेस से डेटा कैसे खींचूं? मैं वर्तमान में निम्नलिखित चयन कथन का उपयोग कर रहा हूं।MySQL क्लोजर टेबल पदानुक्रमित डेटाबेस - सही क्रम में जानकारी को कैसे खींचें
SELECT `TreeData`.`iD`, `TreeData`.`subsectionOf`,
CONCAT(REPEAT('-', `TreePaths`.`len`),`TreeData`.`name`),
`TreePaths`.`len`,`TreePaths`.`ancestor`,`TreePaths`.`descendant`
FROM `TreeData`
LEFT JOIN `TreePaths` ON `TreeData`.`iD` = `TreePaths`.`descendant`
WHERE `TreePaths`.`ancestor` = 1
ORDER BY `TreeData`.`subsectionOrder`
यह सही जानकारी खींचता है लेकिन सही क्रम में नहीं।
नमूना डेटाबेस नमूना डेटा के साथ स्क्रिप्ट बनाते हैं।
-- Simple Sample
SET FOREIGN_KEY_CHECKS=0;
DROP TRIGGER IF EXISTS Tree_Insert;
DROP TRIGGER IF EXISTS Tree_Update;
DROP TABLE IF EXISTS TreePaths;
DROP TABLE IF EXISTS TreeData;
SET FOREIGN_KEY_CHECKS=1;
CREATE TABLE `TreeData` (
`iD` INT NOT NULL, -- PK
`subsectionOf` INT, -- Parent ID & FK
`subsectionOrder` INT, -- Oder of Subsections
`name` NVARCHAR(500) NOT NULL, -- Name for the entry
PRIMARY KEY (`iD`),
FOREIGN KEY (`subsectionOf`) REFERENCES TreeData(`iD`) ON DELETE CASCADE,
INDEX(`name`)
) ENGINE = MYISAM;
-- Trigger to update the EntryPaths table for new entries
DELIMITER //
CREATE TRIGGER `Tree_Insert` AFTER INSERT ON `TreeData` FOR EACH ROW
BEGIN
INSERT INTO `TreePaths` (`ancestor`, `descendant`, `len`)
SELECT `ancestor`, NEW.`iD`, len + 1 FROM `TreePaths`
WHERE `descendant` = NEW.`subsectionOf`
UNION ALL SELECT NEW.`iD`, NEW.`iD`, 0;
END; //
DELIMITER ;
DELIMITER //
CREATE TRIGGER `Tree_Update` BEFORE UPDATE ON `TreeData` FOR EACH ROW
BEGIN
-- From http://www.mysqlperformanceblog.com/2011/02/14/moving-subtrees-in-closure-table/
IF OLD.`subsectionOf` != NEW.`subsectionOf` THEN
-- Remove the node from its current parent
DELETE a FROM `TreePaths` AS a
JOIN `TreePaths` AS d ON a.`descendant` = d.`descendant`
LEFT JOIN `TreePaths` AS x
ON x.`ancestor` = d.`ancestor` AND x.`descendant` = a.`ancestor`
WHERE d.`ancestor` = OLD.`iD` AND x.`ancestor` IS NULL;
-- Add the node to its new parent
INSERT `TreePaths` (`ancestor`, `descendant`, `len`)
SELECT supertree.`ancestor`, subtree.`descendant`, supertree.`len`+subtree.`len`+1
FROM `TreePaths` AS supertree JOIN `TreePaths` AS subtree
WHERE subtree.`ancestor` = OLD.`iD`
AND supertree.`descendant` = NEW.`subsectionOf`;
END IF;
END; //
DELIMITER ;
CREATE TABLE `TreePaths` (
`ancestor` INT NOT NULL,
`descendant` INT NOT NULL,
`len` INT NOT NULL,
PRIMARY KEY (`ancestor`, `descendant`),
FOREIGN KEY (`ancestor`) REFERENCES TreeData(`iD`) ON DELETE CASCADE,
FOREIGN KEY (`descendant`) REFERENCES TreeData(`iD`) ON DELETE CASCADE
) ENGINE = MYISAM;
INSERT INTO `TreeData` VALUES(1, NULL, NULL, 'Root A');
INSERT INTO `TreeData` VALUES(2, 1, 1, 'Item 1');
INSERT INTO `TreeData` VALUES(3, 1, 2, 'Item 2');
INSERT INTO `TreeData` VALUES(4, 1, 3, 'Item 3');
INSERT INTO `TreeData` VALUES(5, 2, 2, 'Item 1 Sub Item 2');
INSERT INTO `TreeData` VALUES(6, 2, 1, 'Item 1 Sub Item 1');
INSERT INTO `TreeData` VALUES(7, 1, 3, 'Item 4');
INSERT INTO `TreeData` VALUES(8, 4, 1, 'Item 3 Sub Item 1');
INSERT INTO `TreeData` VALUES(9, 4, 2, 'Item 3 Sub Item 2');
INSERT INTO `TreeData` VALUES(10, NULL, NULL, 'Root B');
INSERT INTO `TreeData` VALUES(11, 10, 1, 'Item A');
INSERT INTO `TreeData` VALUES(12, 10, 2, 'Item B');
INSERT INTO `TreeData` VALUES(13, 10, 3, 'Item C');
यह केवल काम करता है अगर आपके पेड़ क्रमिक रूप से बनाया गया था। कल्पना करें कि आपकी मूल वस्तु 1 नहीं थी, यह 12 वर्ष का था, यह अब काम नहीं करेगा। अनुक्रम को हटाने के लिए यहां चार नोड्स को ले जाएं और यह प्रिंटिंग टूट जाएगी। किसी के पास दूसरा समाधान है? –
यदि आपकी बंद तालिका में 'पथदर्शी' कॉलम भी शामिल है, तो आप 'GROUP_CONCAT (crumbs.ancestor ऑर्डर द्वारा पथदर्शी) का उपयोग कर सकते हैं। –
@ थॉमस GROUP_CONCAT (DISTINCT crumbs.ancancor 'crumbs.ancancor' द्वारा आदेश) नौकरी करेगा, – kukipei