【问题标题】:Howto design Tables for Navigating Hierarchical Regions with Diamond Structures如何设计用于导航具有菱形结构的分层区域的表
【发布时间】:2010-07-08 07:02:52
【问题描述】:

我们的解决方案需要我们在如下区域的层次结构中工作。

                 STATE
                   |
                DISTRICT
                   |
                 TALUK
                /    \
               /      \
            HOBLI     PANCHAYAT
                \      /     
                 \    /
                  \  /
                VILLAGE

有两种方法可以从 Taluk 导航到村庄。通过 HOBLI 或通过 PANCHAYAT。

我们需要一个 PK(非商业密钥)和一个 SERIAL_NUMBER/ID 用于每个州、区、TALUK、HOBLI、PANCHAYAT、VILLAGE;但是,每个村庄都有 8 个附加属性。

如何在 PostgreSQL 8.4 中设计这种结构?

我之前的经验是在 Oracle 上,所以我想知道如何在 PostgreSQL 8.4 中导航层次结构?如果有的话,该解决方案应该对阅读/导航速度友好。

 ================================================================

Quassnoi : 这是一个示例层次结构

                KARNATAKA
                    |
                    |
              TUMKUR (District)
                    |
                    |
                    |
              KUNIGAL (Taluk)
             /              \
            /                \
           /                  \
      HULIYUR DURGA(Hobli)   CHOWDANAKUPPE(Panchayat)
           \                         /
            \                       /
             \                     /
              \                   /
               \                 /
          Voddarakempapura(Village)
          Ankanahalli(Village)
          Chowdanakuppe(Village)
          Yedehalli(Village)

导航:现在,我将展示 2 个单独的 UI 屏幕,每个屏幕都有单独的可导航层次结构

#1 使用 HOBLI 和 所以,对于#1,我需要从 STATE、DISTRICT(s)、TALUK(s)、HOBLI(s)、VILLAGE(s) 开始的整个树。使用上面的树,我需要

     KARNATAKA (State)
        |
        |
        |---TUMKUR (District)
                 |
                 |
                 |-----KUNIGAL(Taluk)
                                 |
                                 |
                               **|----HULIYUR DURGA(Hobli)**
                                               |
                                               |
                                               |---VODDARAKEMPAPURA(Village)
                                               |
                                               |---Yedehalli(Village)
                                               |
                                               |---Ankanahalli(Village)

#2 使用 PANCHAYAT。 所以,对于#2,我需要从 STATE、DISTRICT(s)、TALUK(s)、PANCHAYAT(s)、VILLAGE(s) 开始的整棵树

     KARNATAKA (state)
        |
        |
        |---TUMKUR (District)
                 |
                 |
                 |-----KUNIGAL(Taluk)
                                 |
                                 |
                               **|----CHOWDANAKUPPE (Panchayat)**
                                               |
                                               |
                                               |---VODDARAKEMPAPURA(Village)
                                               |
                                               |---Ankanahalli(Village)
                                               |
                                               |---Chowdanakuppe(Village)

结果集

应该能够使用以下详细信息创建上述树。 我们需要每个 STATE、DISTRICT、TALUK、HOBLI、PANCHAYAT、VILLAGE 的 PK(非业务 KEY)和 SERIAL_NUMBER/ID 以及关系的名称和级别(类似于 ORACLE 的 LEVEL) .

目前,获取上面的 ResultSet 就可以了。但在未来,我们需要能够在 HOBLI/PANCHAYAT/TALUK 级别进行报告(一些聚合)。

======================================

@Quassnoi #2, 非常感谢,

“如果您计划添加更多层次结构轴,则可能值得创建一个单独的表来存储层次结构(添加了轴字段),而不是将字段添加到表中。”

实际上,我简化了现有要求,以免混淆任何人。 实际层次结构是这样的

                 STATE
                   |
                DISTRICT
                   |
                 TALUK
                /    \
               /      \
            HOBLI     PANCHAYAT
                \      /     
                 \    /
                  \  /
             REVENUE VILLAGE
                   |
                   |
               HABITATION

这种层次结构的示例数据如下所示

                KARNATAKA
                    |
              TUMKUR (District)
                    |
              KUNIGAL (Taluk)
             /              \
            /                \
      HULIYUR DURGA(Hobli)   CHOWDANAKUPPE(Panchayat)
             \                     /
              \                   /
               Thavarekere(Revenue Village)
             /                             \
 Bommanahalli(habitation)             Tavarekere(Habitation)

您的解决方案中的任何内容都会因上述修改而改变吗?

另外,您是否建议我创建另一个如下表来存储 Habitats 的 7 个属性?有没有更好的方法来存储这些信息?

CREATE TABLE habitatDetails
(
        id BIGINT NOT NULL PRIMARY KEY,
        serialNumber BIGINT NOT NULL,
        habitatid BIGINT NOT NULL, -- we will add these details only for habitats
        CONSTRAINT "habitatdetails_fk" FOREIGN KEY ("habitatid")
           REFERENCES "public"."t_hierarchy"("id")
        prop1 VARCHAR(128) ,
        prop2 VARCHAR(128) ,
        prop3 VARCHAR(128) ,
        prop4 VARCHAR(128) ,
        prop5 VARCHAR(128) ,
        prop6 VARCHAR(128) ,
        prop7 VARCHAR(128) ,
);

谢谢,

【问题讨论】:

  • 您所说的“导航”是什么意思?一个村庄可以同时属于hoblipanchayat 吗?
  • navigate :为了在树状结构中将其呈现给用户,需要一个 SQL(或 2)使用 HOBLI 层次结构或 PANCHAYAT 层次结构从 DISTRICT 导航到村庄。
    是的,一个村庄同时属于 HOBLI(在 REVENUE/TAXES 层次结构中)和一个村庄同时属于 PANCHAYAT(在 POLITICAL 层次结构中)。
  • 您能否发布一些示例数据(针对一个村庄)以及您想要获得的结果集?
  • Quassnoi:谢谢。我已经修改(附加)了这个问题,因为评论没有足够的空间!

标签: postgresql navigation hierarchy hierarchical-data


【解决方案1】:
CREATE TABLE t_hierarchy
(
        id BIGINT NOT NULL PRIMARY KEY,
        type VARCHAR(128) NOT NULL,
        name VARCHAR(128) NOT NULL,
        tax_parent BIGINT,
        gov_parent BIGINT,
        CHECK (NOT (tax_parent IS NULL AND gov_parent IS NULL))
);

CREATE INDEX ix_hierarchy_taxparent ON t_hierarchy (tax_parent);

CREATE INDEX ix_hierarchy_govparent ON t_hierarchy (gov_parent);

INSERT
INTO    t_hierarchy
VALUES  (1, 'State', 'Karnataka', 0, 0),
        (2, 'District', 'Tumkur', 1, 1),
        (3, 'Taluk', 'Kunigal', 2, 2),
        (4, 'Hobli', 'Huliyur Durga', 3, NULL),
        (5, 'Panchayat', 'Chowdanakuppe', NULL, 3),
        (6, 'Village', 'Voddarakempapura', 4, 5),
        (7, 'Village', 'Ankanahalli', 4, 5),
        (8, 'Village', 'Chowdanakuppe', 4, 5),
        (9, 'Village', 'Yedehalli', 4, 5)

CREATE OR REPLACE FUNCTION fn_hierarchy_tax(level INT, start BIGINT)
RETURNS TABLE (level INT, h t_hierarchy)
AS
$$
        SELECT  $1, h
        FROM    t_hierarchy h
        WHERE   h.id = $2
        UNION ALL
        SELECT  (f).*
        FROM    (
                SELECT  fn_hierarchy_tax($1 + 1, h.id) f
                FROM    t_hierarchy h
                WHERE   h.tax_parent = $2
                ) q;
$$
LANGUAGE 'sql';

CREATE OR REPLACE FUNCTION fn_hierarchy_tax(start BIGINT)
RETURNS TABLE (level INT, h t_hierarchy)
AS
$$
        SELECT  fn_hierarchy_tax(1, $1);
$$
LANGUAGE 'sql';

CREATE OR REPLACE FUNCTION fn_hierarchy_gov(level INT, start BIGINT)
RETURNS TABLE (level INT, h t_hierarchy)
AS
$$
        SELECT  $1, h
        FROM    t_hierarchy h
        WHERE   h.id = $2
        UNION ALL
        SELECT  (f).*
        FROM    (
                SELECT  fn_hierarchy_gov($1 + 1, h.id) f
                FROM    t_hierarchy h
                WHERE   h.gov_parent = $2
                ) q;
$$
LANGUAGE 'sql';

CREATE OR REPLACE FUNCTION fn_hierarchy_gov(start BIGINT)
RETURNS TABLE (level INT, h t_hierarchy)
AS
$$
        SELECT  fn_hierarchy_gov(1, $1);
$$
LANGUAGE 'sql';

SELECT  ht.level, (ht.h).*
FROM    fn_hierarchy_tax(1) ht;

SELECT  ht.level, (ht.h).*
FROM    fn_hierarchy_gov(1) ht;

主要思想是将两个父母保持在两个不同的领域,并使用CONNECT BY模拟(而不是递归CTE)功能来保持顺序。

如果您打算添加更多层次结构轴,则可能值得创建一个单独的表来存储层次结构(添加了轴字段),而不是将字段添加到表中。

更新:

上述修改会改变您下面的解决方案中的任何内容吗?

不,它会工作的。

“轴”是指层次结构链。目前,你有两个轴:政治等级制度(虽然是hablis)和税收等级制度(通过panchayats)。如果您打算添加更多轴(这当然是不可能的),您可以考虑将层次结构存储在另一个表中并将“轴”字段添加到该表中。同样,您想要这样做是非常不可能的,我只是为可能有类似问题的其他读者提到了这种可能性。

另外,您是否建议我创建另一个如下表来存储 Habitats 的 7 个属性?有没有更好的方法来存储这些信息?

是的,将它们放在单独的表中是个好主意。

【讨论】:

  • 夸斯诺伊:谢谢。我会试一试,让你知道。轴和字段:不确定我理解正确。我在上面的问题中附加了一个澄清,称为 Quassnoi #2。请让我知道这是否是您的意思?谢谢
  • 我试图奖励你赏金,但 stackoverflow 回复说我还有 9 个小时才能这样做。
  • 谢谢。我已经接受了你的回答。在我授予你赏金之前还有 2 个小时。
    我已经在上面的 Quassnoi #3 中要求您再次澄清。你能看看吗?谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 2011-01-08
  • 1970-01-01
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多