首页 > 解决方案 > SQL 多个之间由 or 连接

问题描述

我有一个层次结构作为嵌套集存储在 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 语句的查询?

标签: mysqlsql

解决方案


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

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)或者至少(lft)

当然,您也可以使用UNION ALLs 的派生表,例如

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

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


推荐阅读