Изменение хранимой процедуры MySQL для получения заголовков вместо идентификаторов - PullRequest
1 голос
/ 10 октября 2019

У меня есть база данных MySQL, которая включает в себя таблицу иерархических компонентов (каждый компонент не верхнего уровня имеет родительский компонент)

Включает функцию SQL GetParents(ComponentID), которая возвращает список через запятуюродителя ComponentID с, начиная с прямого родителя и повышаясь. Это работает правильно и по назначению.

Я скопировал эту функцию в GetPath(ComponentID и попытался заставить ее вернуть Title вместо идентификатора, а также изменил порядок, чтобы он начинался с верхародитель и идет вниз, но застрял. Мне удалось изменить порядок и , на ->, а также изменить идентификатор верхнего уровня (0) на (Top Level) (за исключением активов верхнего уровня!), Но я не мог понять, какполучите названия вместо идентификаторов.

К сожалению, sqlfiddle не нравится DELIMITER (есть ли альтернативы?), но ниже приведен код, включая схему таблицы и вставки, которые удовлетворяют следующим примерам:

SELECT GetParents(11); должен вернуть 4,1,0. Сейчас это работает правильно, и я включаю его только для полноты.

SELECT GetPath(11); в настоящее время возвращает (Top Level) -> 1 -> 4, но я хочу, чтобы оно возвращало (Top Level) -> Cars -> Car 1

DROP TABLE IF EXISTS `Components`;
CREATE TABLE `Components` (
  `ComponentID` int(11) NOT NULL,
  `ParentComponentID` int(11) NOT NULL,
  `Title` varchar(250) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `Components`
  ADD PRIMARY KEY (`ComponentID`);

ALTER TABLE `Components`
  MODIFY `ComponentID` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;

INSERT INTO Components (ParentComponentID, Title) VALUES 
(0, 'Cars'),(0,'Trucks'),(0,'Boats');

INSERT INTO Components (ParentComponentID, Title) VALUES 
(1, 'Car 1'),(1,'Car 2'),(1,'Car 3'),(2,'Truck 1'),(3,'Boat 3');

INSERT INTO Components (ParentComponentID, Title) VALUES 
(4, 'Wheel 1'),(4,'Wheel 2'),(4,'Wheel 3'),(4,'Wheel 4');

INSERT INTO Components (ParentComponentID, Title) VALUES 
(5, 'Wheel 1'),(5,'Wheel 2'),(5,'Wheel 3'),(5,'Wheel 4');

-- Functions

DELIMITER $$

DROP FUNCTION IF EXISTS `GetParents` $$
CREATE FUNCTION `GetParents` (GivenID  VARCHAR(1024)) RETURNS varchar(1024) CHARSET latin1
DETERMINISTIC
BEGIN

    DECLARE rv,q,queue,queue_children,front_id VARCHAR(1024);
    DECLARE queue_length,pos INT;

    SET rv = '';
    SET queue = GivenID;
    SET queue_length = 1;

    WHILE queue_length > 0 DO
        SET front_id = queue;
        IF queue_length = 1 THEN
            SET queue = '';
        ELSE
            SET pos = LOCATE(',',queue) + 1;
            SET q = SUBSTR(queue,pos);
            SET queue = q;
        END IF;
        SET queue_length = queue_length - 1;

        SELECT IFNULL(qc,'') INTO queue_children
        FROM (SELECT GROUP_CONCAT(ParentComponentID) qc
        FROM Components WHERE ComponentID = front_id AND ParentComponentID!=ComponentID) A;

        IF LENGTH(queue_children) = 0 THEN
            IF LENGTH(queue) = 0 THEN
                SET queue_length = 0;
            END IF;
        ELSE
            IF LENGTH(rv) = 0 THEN
                SET rv = queue_children;
            ELSE
                SET rv = CONCAT(rv,',',queue_children);
            END IF;
            IF LENGTH(queue) = 0 THEN
                SET queue = queue_children;
            ELSE
                SET queue = CONCAT(queue,',',queue_children);
            END IF;
            SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
        END IF;
    END WHILE;

    RETURN rv;
END $$

DROP FUNCTION IF EXISTS `GetPath` $$
CREATE FUNCTION `GetPath` (GivenID  VARCHAR(1024)) RETURNS varchar(1024) CHARSET latin1
DETERMINISTIC
BEGIN

    DECLARE rv,q,queue,queue_children,front_id VARCHAR(1024);
    DECLARE queue_length,pos INT;

    SET rv = '';
    SET queue = GivenID;
    SET queue_length = 1;

    WHILE queue_length > 0 DO
        SET front_id = queue;
        IF queue_length = 1 THEN
            SET queue = '';
        ELSE
            SET pos = LOCATE(',',queue) + 1;
            SET q = SUBSTR(queue,pos);
            SET queue = q;
        END IF;
        SET queue_length = queue_length - 1;

        SELECT IFNULL(qc,'') INTO queue_children
        FROM (SELECT GROUP_CONCAT(ParentComponentID) qc
        FROM Components WHERE ComponentID = front_id AND ParentComponentID!=ComponentID) A;

        IF LENGTH(queue_children) = 0 THEN
            IF LENGTH(queue) = 0 THEN
                SET queue_length = 0;
            END IF;
        ELSE
            IF LENGTH(rv) = 0 THEN
                SET rv = queue_children;
            ELSE
                IF (queue_children = 0) THEN
                    SET rv = CONCAT('(Top Level) -> ',rv);
                ELSE
                    SET rv = CONCAT(queue_children,' -> ',rv);
                END IF;
            END IF;
            IF LENGTH(queue) = 0 THEN
                SET queue = queue_children;
            ELSE
                SET queue = CONCAT(queue,',',queue_children);
            END IF;
            SET queue_length = LENGTH(queue) - LENGTH(REPLACE(queue,',','')) + 1;
        END IF;
    END WHILE;

    RETURN rv;
END $$

DELIMITER ;

Функциябудет вызываться в контексте SELECT getPath(ComponentID) FROM Components, таблицы, в которой может быть много записей, поэтому было бы хорошо иметь эффективный алгоритм!

Спасибо!

...