Howto design Tables для навигации по иерархическим областям с алмазными структурами - PullRequest
2 голосов
/ 08 июля 2010

Наше решение требует, чтобы мы работали в иерархиях регионов, которые выглядят следующим образом.

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

Существует два способа перейти в деревню из Талука.Либо через HOBLI, либо через PANCHAYAT.

Нам нужен PK (некоммерческий ключ) и SERIAL_NUMBER / ID для каждого STATE, DISTRICT, TALUK, HOBLI, PANCHAYAT, VILLAGE;Однако каждая деревня имеет 8 дополнительных атрибутов.

Как мне спроектировать эту структуру в PostgreSQL 8.4 ?

Мой предыдущий опыт был на Oracle, поэтому мне интересно, как ориентироваться в иерархических структурах в PostgreSQL 8.4?Если вообще, решение должно быть дружественным для READ / скорости навигации.

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

Quassnoi: Вот примерная иерархия

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

NAVIGATE: На данный момент я буду представлять 2отдельные экраны пользовательского интерфейса, каждый из которых имеет отдельные навигационные иерархии

# 1 с использованием HOBLI и, таким образом, для # 1 мне потребуется все дерево, начиная с STATE, DISTRICT (s), TALUK (s), HOBLI (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)

ResultSet

Должны быть в состоянии создать выше деревья со следующими деталями.Нам нужен PK (некоммерческий KEY) и SERIAL_NUMBER / ID для каждого STATE, DISTRICT, TALUK, HOBLI, PANCHAYAT, VILLAGE вместе с именем и УРОВНЕМ отношений (аналогично ORACLE'S 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)

Изменится ли что-нибудь в вашем решении ниже с помощью вышеуказанной модификации?

Кроме того, вы бы порекомендовали мне создать еще одну таблицу, как показано ниже, для хранения 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) ,
);

Спасибо,

1 Ответ

2 голосов
/ 11 июля 2010
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) для сохранения порядка.

Если вы планируетедобавьте еще несколько осей иерархии, возможно, стоит создать отдельную таблицу для хранения иерархий (с добавленным полем оси) вместо добавления полей в таблицу.

Обновление:

Изменится ли что-то в вашем решении из-за вышеуказанной модификации?

Нет, все будет работать нормально.

Под "осями" я подразумеваю цепочки иерархии.В настоящее время у вас есть две оси: политическая иерархия (хотя и хаблис) и налоговая иерархия (через панчаяты).Если вы планируете добавить еще несколько осей (что, конечно, маловероятно), вы можете подумать о сохранении иерархий в другой таблице и добавлении поля «ось» в эту таблицу.Опять же, очень маловероятно, что вы захотите это сделать, я только что упомянул эту возможность для других читателей, у которых может быть похожая проблема.

Кроме того, вы бы порекомендовали мне создать еще одну таблицу, как показано нижехранить 7 свойств мест обитания?Есть ли лучший способ хранить такую ​​информацию?

Да, хранить их в отдельной таблице - хорошая идея.

...