【问题标题】:Row-wise IN BETWEEN comparison in a single SQL statement单个 SQL 语句中的逐行 IN BETWEEN 比较
【发布时间】:2009-08-14 08:26:56
【问题描述】:

给定以下表格:

CREATE TABLE tree (
    id serial NOT NULL,
    name character varying NOT NULL,
    type integer,
    lft integer NOT NULL,
    rgt integer NOT NULL )

CREATE TABLE item (
    id serial NOT NULL,
    name character varying NOT NULL,
    tree_id integer
    CONSTRAINT fk_tree FOREIGN KEY (tree_id) REFERENCES tree (id) )

tree 上的列 lftrgt 使用修改后的前序树遍历 (MPTT) 算法填充。

是否可以在 single 查询中获取所有附加到 type=x 的树节点的项目及其所有后代?

通常,我会在两个单独的查询中这样做:

SELECT lft, rgt FROM tree WHERE type = x;
/* assume it returns two rows: ((10, 20), (27, 30)) */

SELECT item.id, item.name FROM item JOIN tree ON (tree_id = tree.id)
WHERE ((lft >= 10 AND rgt <= 20) OR (lft >= 27 AND rgt <= 30);

关键是我只能执行一条 SQL 语句(在 PostgreSQL 数据库中,如果重要的话)。你能用某种子查询来做到这一点吗?

感谢任何提示。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:
    SELECT  item.*
    FROM    tree tm
    JOIN    tree tc
    ON      tc.lft >= tm.lft
            AND tc.rgt <= tm.rgt
    JOIN    item
    ON      item.tree_id = tc.id
    WHERE   tm.type = x
    

    您可能需要考虑更易于管理的父子模型。

    请参阅我的博客中的这些文章,了解如何在PostgreSQL 8.3 及以下实现它:

    ,在PostgreSQL 8.4:

    【讨论】:

    • item.id 和 tree.id 与存储为 lft 和 rgt 的 MPTT 值无关。树上表项的连接只能通过外键完成。
    • np,感谢您的帮助。树模型必须针对读取性能进行优化,这就是选择 MPTT 模型的原因。你更新的答案正是我想要的。
    • @Haes:请注意,现在的方式(当您将treesitems 视为不同的实体时),它远非最佳。即使使用“位图与”,对两个不同列的范围查询也是非常低效的。在您的场景中,一棵树同时具有个子项和子树的情况是否真实存在?
    【解决方案2】:

    好吧,如果您在为给定的数据结构编写查询时遇到问题,也许您应该考虑使用其他数据结构?嵌套集(您在此处显示的内容)看起来很酷,但在向它们编写查询时却很痛苦。

    也许你可以使用this 之类的东西(披露:这是我博客上的帖子)。

    【讨论】:

      猜你喜欢
      • 2018-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 2017-01-31
      • 1970-01-01
      相关资源
      最近更新 更多