Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Иерархия / 25 сообщений из 39, страница 1 из 2
28.07.2009, 15:05
    #36113564
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
есть табличка, типа есть группы в них группы или товары (как файлы-папки):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE GOOD ( --товары
      ID Integer NOT NULL, --первичный ключ
      LEFTBOUND Integer NOT NULL,
      RIGHTBOUND Integer NOT NULL,
      PARENT Integer,--сылка на группу владельца, для первого уровня NULL
      NAME Varchar( 50 ) NOT NULL, --наименование группы или товара
      ISGROUP Integer NOT NULL --признак группы: 0,1
);
правило: если товар А лежит в группе Б а та в группе С то:
Код: plaintext
C.LEFTBOUND<B.LEFTBOUND<A.LEFTBOUND=A.RIGHTBOUND<=B.RIGHTBOUND<=C.RIGHTBOUND
то есть диапозон LEFTBOUND ... RIGHTBOUND групп охватывает вложенные записи (групп и товаров)
для товаров (не групп) верно: LEFTBOUND=RIGHTBOUND

требуется написать запрос, упорядочивающий записи по иерархии, а среди записей одного уровня должны вначале идти группы, например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Группа 1
 Группа 1.1
  Товар 1.1.1
  Товар 1.1.2
 Товар 1.2
 Товар 1.3
Группа 2
 Группа 2.1
 Группа 2.2

смог построить запрос по-иерархии, но не добился чтобы группы в одном уровне были сверху:

Код: plaintext
1.
2.
3.
4.
select g.ID, g.Name, g.ISGROUP, count(g2.ID) as glevel
from GOOD g
left join GOOD g2 on (g.LEFTBOUND between g2.LEFTBOUND and g2.RIGHTBOUND)
group by g.ID, g.Name, g.ISGROUP, g.LEFTBOUND
order by g.LEFTBOUND

поле glevel отвечает за уровень вложенности записи

С уважением, Naf
...
Рейтинг: 0 / 0
28.07.2009, 15:15
    #36113594
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> требуется написать запрос

Исправьте структуру. Не читайте Celco, его примеры носят исключительно теоретический характер и на практике применяться не должны.
...
Рейтинг: 0 / 0
28.07.2009, 15:21
    #36113619
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> требуется написать запрос

Исправьте структуру. Не читайте Celco, его примеры носят исключительно теоретический характер и на практике применяться не должны.
это эксперимет, при малом и неоперативном изменении данных удобно (структура в основном на чтение)
выход видится один - при вставке новых групп анализировать и сдвигать LEVELBOUND вниз у элементов-не-групп
...
Рейтинг: 0 / 0
28.07.2009, 15:30
    #36113647
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> это эксперимет

Как получить иерархию наиболее извращенным способом? Вы понимаете, что невозможно придумать условия, которым такая реализация будет удовлетворять?

> при малом и неоперативном изменении данных удобно (структура в основном на чтение)

Удобно - это когда все иерархии в базе данных имеют общую каноническую модель и когда view получаются простыми и безгеморройными.
...
Рейтинг: 0 / 0
28.07.2009, 15:34
    #36113659
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> это эксперимет

Как получить иерархию наиболее извращенным способом? Вы понимаете, что невозможно придумать условия, которым такая реализация будет удовлетворять?

> при малом и неоперативном изменении данных удобно (структура в основном на чтение)

Удобно - это когда все иерархии в базе данных имеют общую каноническую модель и когда view получаются простыми и безгеморройными. Прошу Вас предложить свой вариант иерархии
...
Рейтинг: 0 / 0
28.07.2009, 15:35
    #36113667
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
Сформулируйте задачу.
...
Рейтинг: 0 / 0
28.07.2009, 15:47
    #36113707
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621Сформулируйте задачу.
Есть справочник товаров, он должен быть иерархический. У одного элемента может быть только один владелец-группа. Вложенность не ограниченная.
Необходимо простым способом (одним запросом желательно) выводить его в иерархическом виде (это текущий топик).
Также соединять другие таблицы с ней, выводя данные по записям справочника и агрегирующие по группам. Например (упрощенно) есть также таблица
Код: plaintext
1.
2.
3.
4.
CREATE TABLE SALE (--продажи
       ID Integer NOT NULL, 
       GOOD Integer NOT NULL, --ссылка на исходный справочник
       SUMMA Numeric( 15 , 3 ) NOT NULL --сумма продажи
);
необходимо вывести таблицу в виде:
Код: plaintext
1.
2.
3.
4.
Молочные продукты 150
  Молоко          100
    Молоко 3%      70
    Молоко 6%      30
  Кефир 3%         50
вместо отступов можно выводить уровень записи(число вложений в группы)
...
Рейтинг: 0 / 0
28.07.2009, 15:53
    #36113729
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> Есть справочник товаров

Характер справочника? Правила классификации? Предмет классификации? Область применения?
...
Рейтинг: 0 / 0
28.07.2009, 15:55
    #36113745
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> Есть справочник товаров

Характер справочника? Правила классификации? Предмет классификации? Область применения?Правила и остальное на усмотрение пользователей оставляются. Для примера, посмотрите 1С, вот аналог справочника Номенклатура там.
...
Рейтинг: 0 / 0
28.07.2009, 16:22
    #36113867
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
н-да, не все так просто

внутри одной группы нужно сортировать более хитро:
сначала группы потом остальные записи, но и те и те по алфавиту

С уважением, Naf
...
Рейтинг: 0 / 0
28.07.2009, 16:25
    #36113877
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> Правила и остальное на усмотрение пользователей

Тогда задача не имеет простого решения. Невозможно классифицировать все, что угодно, каким угодно образом.
А если не париться, то три подзадачи: собственно классификатор (включая зависимости и пр.), предмет классификации (в данном случае товары) и собственно связи между классификатором и предметами классификации.

> посмотрите 1С

Не напрягайте модератора. Одинце - то же самое, что и писанина Celco: для практического применения это непригодно.
...
Рейтинг: 0 / 0
28.07.2009, 16:32
    #36113910
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> Правила и остальное на усмотрение пользователей

Тогда задача не имеет простого решения. Невозможно классифицировать все, что угодно, каким угодно образом.
А если не париться, то три подзадачи: собственно классификатор (включая зависимости и пр.), предмет классификации (в данном случае товары) и собственно связи между классификатором и предметами классификации.

> посмотрите 1С

Не напрягайте модератора. Одинце - то же самое, что и писанина Celco: для практического применения это непригодно.
Не надо все, надо - товары. каким образом? ну допустим по номенклатурным группам, заданным на предприятие. Например: группа "Молочные продукты" включает в себя группы "Молоко", "Кефир"...
Группа "Молоко" состоит из товаров "Молоко 3%", "Молоко 6%" ...
Товары могут иметь произвольное число вложений. Например "Молоко 3%" - 3 уровня вложенности, а "Хлеб форомовой" - 2 уровня.
А насчет непрактичности 1С, жизнь показывает обратное.
...
Рейтинг: 0 / 0
28.07.2009, 16:43
    #36113954
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> группа "Молочные продукты" включает в себя группы "Молоко", "Кефир"...

Так и делайте, какие проблемы? Классификатор - отдельно, товары - отдельно, связи - отдельно.
...
Рейтинг: 0 / 0
28.07.2009, 16:53
    #36113994
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> группа "Молочные продукты" включает в себя группы "Молоко", "Кефир"...

Так и делайте, какие проблемы? Классификатор - отдельно, товары - отдельно, связи - отдельно.Я думал над этим, чтоб группы вынести в отдельную таблицу, но что это дает, если число вложений групп заранее неизвестно? тоже самое, что они в общей таблице. В смысле та же проблема упорядочивания.
...
Рейтинг: 0 / 0
28.07.2009, 17:07
    #36114032
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
> что это дает

Корректную модель.

> число вложений групп заранее неизвестно

И? Для каждого элемента классификатора храните уровень и глубину, если всегда нужно это знать.
...
Рейтинг: 0 / 0
28.07.2009, 17:12
    #36114055
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621> что это дает

Корректную модель.

> число вложений групп заранее неизвестно

И? Для каждого элемента классификатора храните уровень и глубину, если всегда нужно это знать."уровень и глубину" а простите что есть глубина? уровень я определял количество вложений записи в другие. Эти данные я и так вытащить могу.
Мне нужна упорядоченность:
- по иерархии, внутри нее
- по признаку группа или нет (сначала группы), среди них по алфавиту
...
Рейтинг: 0 / 0
28.07.2009, 17:13
    #36114062
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
в общем, вы можете конкретный (достаточно простой) пример привести
желательно без рекурсивного вызова процедур
С уважением, Naf
...
Рейтинг: 0 / 0
28.07.2009, 17:32
    #36114126
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
В общем задача такая: какая наиболее оптимальная структура таблицы справочника, чтобы наиболее просто получать иерархический список (упорядоченность по иерархии и доп. полю, например наименованию или признаку группы + наименованию)
Соответственно, достаточно просто получать агрегатные функции из других таблиц с учетом иерархии.
Достаточно просто - это одним запросом и без рекурсии хранимых процедур.

С уважением, Naf
...
Рейтинг: 0 / 0
29.07.2009, 09:16
    #36114756
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
Когда в практике ты "ноль" можно по теоретизировать.
Итак, пусть есть таблица представляющая собой некое множество записей, на котором хотим задать отношение полного порядка (а попросту, упорядочить каким-то способом). Обозначим A>>B если в нашем упорядочивании запись A идет раньше B.
Введем функцию r(A,B) =1, если A>>B и =0 иначе.
Очевидно, что r(A,A)=0; r(A,B)=1-r(B,A); если r(A,B)=r(B,C)=1 тогда r(A,С)=1.
Тогда функция R(A)=Sum(r(A,B),B-пробегает все множество) принимает различные значения 0,1,...,Count(*)-1 и задает тот же порядок на целых числах.
Переводя в SQL, получаем запрос "универсального" упорядочивания:
Код: plaintext
1.
2.
3.
4.
SELECT A.Х
FROM T as A
LEFT JOIN T as B on ( 1 = 1 )
GROUP BY A.X
ORDER BY SUM(r(A,B)) DESC --запись формальная естественно
или тоже самое
Код: plaintext
1.
2.
3.
4.
SELECT A.Х
FROM T as A
LEFT JOIN T as B on (r(A,B)= 1 )
GROUP BY A.X
ORDER BY COUNT(B.Х) DESC
естественно, не стоит применять такой запрос при простом упорядочивании. Я вообще не знаю где его можно применить ))).

Вернемся к текущей задаче. Необходимо упорядочить множество по-иерархии (обозначим >>) и внутри одной ветки иерархии по другому признаку, например паре IsGroup,Name (обозначим >).
Итак, для каждой записи можно указать "родительскую", на которую ссылается Parent. Для каждой записи A можно записать родительский ряд:
A=A0<<A1<<...<<An=NULL где Ai.Parent = A(i+1).
Для пары (A,B) минимальным предком X назовем запись наибольшего уровня вложенности, одновременно встречающееся в родительских рядах A и B (возможно NULL). Если A и B не расположены в одном родительском ряду, то минимальные индивидуальные родители относительно A и B это элементы в родительских рядах An<<X и Bm<<X (предшествующие X непосредственно).
Тогда введенная ранее функция r(A,B) равна 1 тогда и только тогда, когда:
1. B!=A и A лежит в родительском ряду B.
либо
2. An>Bm (верно второе упорядочивание).
Как видно из написанного нам понадобится использование LEFTBOUND и RIGHTBOUND, но придется использовать многократное соединение таблицы самой с собой. А именно: найти минимального предка, найти индивидуальных предков и сравнить их.
Но, зачастую, практика это не теория, надеюсь на более простое решение задачи.

С уважением, Naf
...
Рейтинг: 0 / 0
29.07.2009, 11:08
    #36114993
guest_20040621
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
Вы не имеете ни малейшего представления ни о классификации, ни о проектировании, ни о теории множеств. Я не могу тратить свое время на глупые измышления.
...
Рейтинг: 0 / 0
29.07.2009, 11:12
    #36115007
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
guest_20040621Вы не имеете ни малейшего представления ни о классификации, ни о проектировании, ни о теории множеств. Я не могу тратить свое время на глупые измышления.От Вас я тоже никакой конкретики не увидел. Можете не тратить свое время на меня, а я свое на Вас.
...
Рейтинг: 0 / 0
29.07.2009, 12:50
    #36115303
_мод
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
Вывод дерева с сортировкой внутри каждого уровня:
Код: plaintext
1.
2.
3.
4.
5.
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id =  100 
CONNECT BY PRIOR employee_id = manager_id
ORDER SIBLINGS BY last_name; 
...
Рейтинг: 0 / 0
29.07.2009, 14:13
    #36115551
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
н-да, без специфики серверов, то есть максимально переносимо между СУБД вышло вот так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT 
T.ID1 ID ,T.NAME1 NAME, COUNT(DISTINCT GLEV.ID) LEV
FROM
(SELECT G1.ID ID1, G2.ID ID2, MAX(MP.LEFTBOUND) MPL, MIN(MP.RIGHTBOUND) MPR, G1.LEFTBOUND GL1, G2.LEFTBOUND GL2, G1.NAME NAME1 
FROM GOOD G1
LEFT JOIN GOOD G2 ON NOT(G1.ID=G2.ID)
LEFT JOIN GOOD MP ON ((G1.LEFTBOUND BETWEEN MP.LEFTBOUND AND MP.RIGHTBOUND) AND (G2.LEFTBOUND BETWEEN MP.LEFTBOUND AND MP.RIGHTBOUND))
GROUP BY G1.ID, G2.ID, G1.LEFTBOUND, G2.LEFTBOUND, G1.NAME) T 
LEFT JOIN GOOD MP0 ON (MP0.LEFTBOUND = T.MPL)
LEFT JOIN GOOD GI1 ON ((GI1.PARENT = MP0.ID) OR ((MP0.ID IS NULL) AND (GI1.PARENT IS NULL))) AND (T.GL1 BETWEEN GI1.LEFTBOUND AND GI1.RIGHTBOUND)
LEFT JOIN GOOD GI2 ON ((GI2.PARENT = MP0.ID) OR ((MP0.ID IS NULL) AND (GI2.PARENT IS NULL))) AND (T.GL2 BETWEEN GI2.LEFTBOUND AND GI2.RIGHTBOUND)
LEFT JOIN GOOD GLEV ON (T.GL1 BETWEEN GLEV.LEFTBOUND AND GLEV.RIGHTBOUND) 
GROUP BY T.ID1, T.NAME1
ORDER BY
      SUM(
      CASE
        WHEN T.ID1=MP0.ID THEN  1 
        WHEN T.ID2=MP0.ID THEN  0 
        WHEN (GI1.ISGROUP>GI2.ISGROUP) THEN  1 
        WHEN (GI1.ISGROUP<GI2.ISGROUP) THEN  0         
        WHEN (GI1.NAME<GI2.NAME) THEN  1         
        ELSE  0 
      END) DESC
...
Рейтинг: 0 / 0
29.07.2009, 14:14
    #36115554
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
интересно насколько это хуже рекурсии?
С уважением, Naf
...
Рейтинг: 0 / 0
29.07.2009, 15:08
    #36115711
Naf
Naf
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Иерархия
поправить упорядочивание на:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
ORDER BY
     COUNT( DISTINCT
     CASE
       WHEN T.ID1=MP0.ID THEN ID2
       WHEN T.ID2=MP0.ID THEN NULL
       WHEN (GI1.ISGROUP>GI2.ISGROUP) THEN ID2
       WHEN (GI1.ISGROUP<GI2.ISGROUP) THEN NULL        
       WHEN (GI1.NAME<GI2.NAME) THEN ID2        
       ELSE NULL
     END)
...
Рейтинг: 0 / 0
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Иерархия / 25 сообщений из 39, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]