mysql - SQL 多个由 or 连接的 between

标签 mysql sql

我有一个层次结构作为嵌套集存储在 mySQL 数据库中,我想找到一个节点的所有父节点,我可以这样做:

SELECT id FROM nested_set WHERE 837461 BETWEEN lft AND rgt;

但我想对可能有大量节点(比如 10,000)执行此操作。我可以通过将一组 BETWEEN 链接在一起来做到这一点,例如

SELECT id FROM nested_set WHERE 
    44102 BETWEEN lft AND rgt OR
    837461 BETWEEN lft AND rgt OR
    164462 BETWEEN lft AND rgt OR
    566562 BETWEEN lft AND rgt OR
    768916 BETWEEN lft AND rgt OR 
    ...

但这看起来很乏味,我猜可能会超过 SQL 语句的大小。有没有比使用 10,000 个链式 OR 语句创建查询更有效的方法?

最佳答案

我不确定这是否符合改进或解决方案的条件,但我会试一试:正如我已经评论过的,您可以使用存储节点的临时表。

CREATE TEMPORARY TABLE nodes
                       (node integer,
                        INDEX (node));

INSERT INTO nodes
            (node)
            VALUES (44102),
                   (837461),
                   (164462),
                   (566562),
                   ...;

然后您可以使用它通过内部联接执行您的SELECT

SELECT ns.id
       FROM nested_set ns
            INNER JOIN nodes n
                       ON n.node BETWEEN ns.lft
                                         AND ns.rgt);

请注意,如果节点不是唯一的或多个给定节点在同一范围内,您可能需要使用 DISTINCT

另一种方法是使用 EXISTS

SELECT ns.id
       FROM nested_set ns
       WHERE EXISTS (SELECT *
                            FROM nodes n
                            WHERE n.node BETWEEN ns.lft
                                                 AND ns.rgt);

临时表上的索引可能支持性能。对于表 nested_set,我会尝试在 (lft, rgt, id)(lft, rgt) 或至少 上建立索引(左)

当然你也可以使用UNION ALL的派生表

...    
(SELECT 44102 node
 UNION ALL
 SELECT 837461 node
 UNION ALL
 SELECT 164462
 UNION ALL
 SELECT 566562
 ...) nodes
...

从中加入或选择存在。但是那样的话就没有临时表中的支持索引了。然而,对于较小的集合,该索引可能没有那么大的权重。

关于mysql - SQL 多个由 or 连接的 between,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57237169/

相关文章:

sql - 如何在 Oracle 数据库中创建临时表?

sql - 更新表变量

sql - MSSQL 查询帮助?应该很容易,但我必须要更多的咖啡?

mysql - 优化两个大表之间的Update Join

php - PHP和MySQL:mysqli_num_rows()期望参数1为mysqli_result,给定 bool 值

mysql - 使用逻辑 ER 的 SQL 数据库设计

mysql - 销售点定义

php - 如何从 mysql 获取列名?

mysql - UNION SELECT 不显示所有列

mysql - 如何对重复的对进行分组并对它们编写查询?