MySQL, MariaDB: Как мне создать дочерний родительский иерархический рекурсивный запрос? - PullRequest
0 голосов
/ 20 сентября 2019

У меня следующий запрос MySQL:

SELECT * FROM (SELECT * FROM paper ORDER BY id DESC) paper_sorted,
        (SELECT @pv := 26) initialisation
        WHERE find_in_set(id, @pv)
        AND length(@pv := concat(@pv, ',', last_id))
        ORDER BY @pv ASC LIMIT 0,15

http://sqlfiddle.com/#!9/9e2df/24

Это прекрасно работает в MySQL;Тем не менее, я работаю с базой данных MariaDB, и этот запрос не работает.В любом случае, переписать это, чтобы оно работало как для MySQL, так и для MariaDB?

Схема базы данных:

CREATE TABLE paper (
    id INT,
    last_id INT
);

INSERT INTO paper VALUES (19, 0);
INSERT INTO paper VALUES (20, 19);
INSERT INTO paper VALUES (21, 20);
INSERT INTO paper VALUES (22, 21);
INSERT INTO paper VALUES (23, 19);
INSERT INTO paper VALUES (24, 23);
INSERT INTO paper VALUES (25, 23);
INSERT INTO paper VALUES (26, 24);

MariaDB v. 10.3.18;MySQL v. 5.7.27

Этот запрос SQL должен получить все идентификаторы Parent.Как и в примере запроса, переменная @pv равна 26 и, следовательно, получает 26-> 24-> 23-> 19.

Однако для MariaDB это не работает.Он возвращает только один ряд, который в MariaDB равен 26.Как переписать этот запрос для работы с MariaDB и MySQL?

1 Ответ

1 голос
/ 20 сентября 2019

Вы должны быть в состоянии переписать запрос как Recursive CTE .Они были добавлены в MariaDB 10.2 и позволяют запрашивать иерархические структуры данных с помощью SQL.

Что-то в этом духе должно работать:

WITH RECURSIVE p AS (
    SELECT * FROM paper WHERE id = 26
    UNION
    SELECT c.* FROM paper AS c, p WHERE p.last_id = c.id
) SELECT * FROM p ORDER BY id ASC LIMIT 15;

Редактировать: Если выЧтобы SQL был обратно совместим со старыми версиями, вы можете использовать хранимую процедуру для достижения того же результата.

DELIMITER // ;

CREATE OR REPLACE PROCEDURE p1(IN id_in INT)
BEGIN
    DECLARE i INT DEFAULT id_in;
    CREATE OR REPLACE TEMPORARY TABLE results LIKE paper;

    WHILE i IS NOT NULL DO
          INSERT INTO results SELECT p.id, p.last_id FROM paper AS p WHERE p.id = i;
          SET i = (SELECT r.last_id FROM results AS r WHERE r.id = i LIMIT 1);
    END WHILE;

    SELECT * FROM results;
    DROP TEMPORARY TABLE results;
END;
//

DELIMITER ; //
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...