mysql - MySQL、MariaDB:如何创建子父分层递归查询?
问题描述
我有以下 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 诉 10.3.18;MySQL v. 5.7.27
此 SQL 查询应获取所有父 ID。在示例查询中,@pv
变量为 26,因此得到 26->24->23->19。
但是,这不适用于 MariaDB。它只返回一行,在 MariaDB 中为 26。如何重写此查询以同时适用于 MariaDB 和 MySQL?
解决方案
您应该能够将查询重写为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 ; //
推荐阅读
- rest - SOAP 是唯一与服务相关的 OPC UA 实现吗?它与 Rest 相比如何?
- java - 未找到 Java org.apache.http.ssl.SSLContext
- javascript - Javascript - 查看数字列表时如何返回 Nan
- node.js - 错误:4 DEADLINE_EXCEEDED:CloudRUN 已超过截止日期
- android - 如何在库模块中为 firebase 性能监视器添加自定义跟踪?
- swiftui - 带有#available 的条件修饰符未正确执行
- javascript - 如何在js中对根对象做getter?
- python - 根据 Python 中的参数数量调用函数
- python - 这个算法中的 Python 尾递归优化?
- django - Django __exact 查询集过滤器 - 区分大小写不能按预期工作