Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.01.2015, 02:40   #11
bidzina
Подтвердите свой е-майл
 
Регистрация: 10.01.2013
Сообщений: 16
По умолчанию

создал 3 таблицы-фирмы,филиалы,подразделения, чтобы создать связь между иерархиями. связь между ними как предлагал Streletz:
Код:
CREATE TABLE "LEVEL1"    -фирмы
(
  "ID"	INTEGER NOT NULL,
  "NAME"	VARCHAR(30),
 PRIMARY KEY ("ID")
);
Код:
CREATE TABLE "LEVEL2"   -филиалы
(
  "ID"	INTEGER NOT NULL,
  "NAME"	VARCHAR(30) NOT NULL,
  "PARENT_ID"	INTEGER NOT NULL,
 PRIMARY KEY ("ID")
);
ALTER TABLE "LEVEL2" ADD FOREIGN KEY ("PARENT_ID") REFERENCES "LEVEL1" ("ID");
Код:
CREATE TABLE "LEVEL3"   -подразделения
(
  "ID"	INTEGER NOT NULL,
  "NAME"	VARCHAR(30),
  "PARENT_ID"	INTEGER NOT NULL,
  "PARENT_ID2"	INTEGER NOT NULL,
 PRIMARY KEY ("ID")
);
ALTER TABLE "LEVEL3" ADD FOREIGN KEY ("PARENT_ID") REFERENCES "LEVEL1" ("ID");
ALTER TABLE "LEVEL3" ADD FOREIGN KEY ("PARENT_ID2") REFERENCES "LEVEL2" ("ID");
но получаю
Код:
LEVEL1:
ID      NAME
1       ооо "ABC"
2       ооо "DEF"       

LEVEL2:
ID      NAME              PARENT_ID
1      филиал "ABC"         1
2      филиал "DEF"         2

LEVEL3:
ID      NAME                        PARENT_ID   PARENT_ID2
1      подразд. №1"ABC"           1                   1
2      подразд.№2 "ABC"           1                   2
3      подразд.№1 "DEF"           2                   2


select "ID","NAME" from LEVEL1 
        union
select "ID","NAME" from LEVEL2
        union
select "ID","NAME" from LEVEL3
резултат запроса приблизительно такой:
Код:
ID             NAME
1              подразд. №1"ABC"   
1              филиал "ABC"  
1              ооо "ABC"
2              подразд. №2"ABC"
2              филиал "ABC"    
2              ооо "DEF"
3              подразд.№1 "DEF"
как изменить запрос- как добавить Parent_id?

здесь предлагают добавить поле LEVEL :http://www.opennet.ru/base/dev/hierarchy_sql.txt.html

select "ID",'1' as "LEVEL","NAME" from LEVEL1
union
select "ID",'2' as "LEVEL","NAME" from LEVEL2
union
select "ID",'3' as "LEVEL","NAME" from LEVEL3

Код:
получил тот-же запрос, но пустим LEVEL-ом:
ID     LEVEL       NAME
1                      подразд. №1"ABC"   
1                      филиал "ABC"  
1                      ооо "ABC"
2                      подразд. №2"ABC"
2                     филиал "ABC"    
2                     ооо "DEF"
3                     подразд.№1 "DEF"

Последний раз редактировалось Stilet; 28.01.2015 в 07:35.
bidzina вне форума Ответить с цитированием
Старый 28.01.2015, 08:18   #12
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
как изменить запрос- как добавить Parent_id?
Код:
select id, name, null as parent_id from level1
union
select id, name, parent_id from level2
union 
,,,,,
НО! на мой взгляд навигацию удобнее делать с помощью подчиненных таблиц а не сваливать в одну кучу фирмы(level1) и ящики(levelX)

Код:
select id, name from level1 

select id, name from level2 where parent_id=<и здесь подставлять данные из предыдущего  запроса>

select id, name from level3 .....
p.S. это более соответствует заявлению об иерархической структуре данных


если что-то можно свалить в одну кучу, значит они изначально должны быть в одной таблице.
если при этом они должны уметь разделяться, у них должен быть признак по которому они смогут разделиться (поле level которое посоветовали на другом форуме)

собрать все данные (level1, level2, level3) в одну таблицу (firms)

Код:
id integer not null, (primarykey)
name  varchar,
level integer,  ---- =1-firms =2-filials 3-departaments .....
parent_id integer (foreign key на СВОЕ же поле id)
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 28.01.2015 в 08:49.
evg_m вне форума Ответить с цитированием
Старый 28.01.2015, 09:22   #13
lomastr_
Форумчанин
 
Регистрация: 16.01.2015
Сообщений: 672
По умолчанию

Цитата:
3 таблицы-фирмы,филиалы,подразделения
это все одна суть, потому их в 1 таблицу объединить.
lomastr_ вне форума Ответить с цитированием
Старый 28.01.2015, 23:47   #14
bidzina
Подтвердите свой е-майл
 
Регистрация: 10.01.2013
Сообщений: 16
По умолчанию

lomastr_,
Цитата:
это все одна суть, потому их в 1 таблицу объединить.
Это верно, но я хочу решить проблему связывания таблиц в иерархии, имена таблиц не имеет значения.
Значить, есть таблицы Contragents и warehouses. "Мой фирмы" входят в таблице Contragents. Если филиалы и подразделения добавлю в Contragents и сделаю вложенность,с помощью поля Parent_id смогу получить одну иерархию, а поля для стеллажей и ящиков добавлю в warehouses и тоже с помощью поля Parent_id получу иерархию склада. Но!... Как потом связать эти 2 иерархии?
Поэтому пробовал сделать по-другому: Создать цепь таблиц, связанных внешними ключами. сделал запрос как предлагал evg_m:
Код:
select id, name, null as parent_id from level1
union
select id, name, parent_id from level2
union 
,,,,,
IBConsole выводил ощибку, потом изменил null на 0, добавил в таблицах поля level(=1 для таблицы Level1, то есть Firms,2 для таблицы Level2, то есть филиалы и 3 для таблицы Level3- подразделения):
Код:
select id, 0 as parent_id, lev, name from level1
union
select id, parent_id,lev, name from level2
union
select id, parent_id, lev, name from level3
резултат:
Код:
ID      PARENT_ID     LEVEL        NAME
1           0           1             AAA Ltd
1           1           2             Branch #1 of "AAA"
1           1           3             Departament  №1 of AAA
2           0           1             BBB Ltd
2           1           3             Departament  №2 of AAA
2           2           2             Branch #1 of "BBB"
3           2           2             Branch #2 of "BBB"  
3           2           3             Departament  №1 of BBB
как выдите Parent_ID собраны из всех 3 таблиц и с помощью их невозможно построить DbTree.

Последний раз редактировалось bidzina; 28.01.2015 в 23:51.
bidzina вне форума Ответить с цитированием
Старый 29.01.2015, 02:28   #15
lomastr_
Форумчанин
 
Регистрация: 16.01.2015
Сообщений: 672
По умолчанию

связывание делается через FOREIGN KEY, если его мало, добавляют признаки..
для чего вам еще какието левелы? и длинные юнионы
lomastr_ вне форума Ответить с цитированием
Старый 29.01.2015, 05:01   #16
bidzina
Подтвердите свой е-майл
 
Регистрация: 10.01.2013
Сообщений: 16
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
А, т.е. СУБД менять нельзя... Тогда сложнее... Сразу так и не скажешь как лучше поступить. XML походу тоже отпадает.
Получается что в каждой таблице тогда нужно делать отдельное поле, где будет храниться ParentID. Сколько таблиц столько и полей. Другое пока в голову не идет.
Если в каждой таблице добавлю ParentID, получу кучу таблиц, а как потом их связать? Это будет труднее!
Тут есть статья про аналогичную ситуацию- когда создаётся цепь таблиц: http://www.opennet.ru/base/dev/hierarchy_sql.txt.html
Цитата:
Одним из вариантов хранения таких иерархий является поуровневое
хранение в различных таблицах. Например, таблица CATALOG_LEVEL_1
хранит все элементы первого уровня вложенности, таблица
CATALOG_LEVEL_2 - второго, и т.д. Ниже приведено описание такой
структуры для случая трехуровневой иерархии.

CREATE TABLE "CATALOG3_LEVEL1" (
"ID" INTEGER NOT NULL PRIMARY KEY,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL
);
CREATE TABLE "CATALOG3_LEVEL2" (
"ID" INTEGER NOT NULL UNIQUE,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL,
"PARENT_ID" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL1"("ID"),
PRIMARY KEY("ID","PARENT_ID")
);
CREATE TABLE "CATALOG3_LEVEL3" (
"ID" INTEGER NOT NULL UNIQUE,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL,
"PARENT_ID" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL1"("ID"),
"PARENT_ID2" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL2"("ID"),
PRIMARY KEY ("ID", "PARENT_ID", "PARENT_ID2")
);

.........

Получение всех потомков

Довольно часто возникает задача получения всех, в том числе и не
прямых потомков данного элемента. Рассмотрим решение этой задачи для приведенных структур.

структура с потабличным хранением уровней

Потомки данного элемента содержатся в "нижележащих" таблицах и имеют как часть составной ссылки на предка в одном из полей значение ID предка. Общий список потомков можно получить объединением (UNION) запросов.
select "ID",'1' as "LEVEL" from CATALOG3_LEVEL2 where PARENT_ID = 1
union
select "ID",'2' as "LEVEL" from CATALOG3_LEVEL3 where PARENT_ID = 1
Ввод дополнительного поля LEVEL в запрос обусловлен тем, что потомки
элемента в разных таблицах могут иметь одинаковые ID и при объединении запросов вместо нескольких строк в результате будет получена одна. Еще одна проблема, приводящая к необходимости ввода дополнительного поля в запрос, т.к. надо знать, из какой таблицы выбран данный ID.
и аналогично я создал 3 таблицы: Level1,Level2,Level3:
Код:
CREATE TABLE "LEVEL1" 
(
  "ID"	INTEGER NOT NULL,
  "LEV"	INTEGER,
  "NAME"	VARCHAR(200),
 PRIMARY KEY ("ID")


CREATE TABLE "LEVEL2" 
(
  "ID"	INTEGER NOT NULL,
  "PARENT_ID"	INTEGER NOT NULL,
  "LEV"	INTEGER,
  "NAME"	VARCHAR(200) NOT NULL,
 PRIMARY KEY ("ID")
);
ALTER TABLE "LEVEL2" ADD FOREIGN KEY ("PARENT_ID") REFERENCES "LEVEL1" ("ID");

CREATE TABLE "LEVEL3" 
(
  "ID"	INTEGER NOT NULL,
  "PARENT_ID"	INTEGER NOT NULL,
  "PARENT_ID2"	INTEGER NOT NULL,
  "LEV"	INTEGER,
  "NAME"	VARCHAR(200),
 PRIMARY KEY ("ID")
);
ALTER TABLE "LEVEL3" ADD FOREIGN KEY ("PARENT_ID") REFERENCES "LEVEL1" ("ID");
ALTER TABLE "LEVEL3" ADD FOREIGN KEY ("PARENT_ID2") REFERENCES "LEVEL2" ("ID");
а запрос выглядит так:
Код:
select id, 0 as parent_id, lev, name from level1
union
select id, parent_id,lev, name from level2
union
select id, parent_id,  lev, name from level3
но результат не тот:
Код:
ID      PARENT_ID     LEVEL        NAME
1           0           1         BBB Ltd
1           1           2         Branch #1 of "AAA"
1           1           3         Departament  №1 of AAA
2           0           1         AAA Ltd
2           1           3         Departament  №2 of AAA
2           2           2         Branch #1 of "AAA"
3           2           2         Branch #2 of "BBB"  
3           2           3         Departament  №1 of BBB
как выдите Parent_ID собраны из всех 3 таблиц и с помощью их невозможно построить TreeView?! Знаю как строится древовидная структура на основе одной таблицы, но здесь совсем другая ситуация- ParentID не указывает на предка.
Наверно неправильный запрос пишу! Как преодолеть?
bidzina вне форума Ответить с цитированием
Старый 29.01.2015, 05:08   #17
bidzina
Подтвердите свой е-майл
 
Регистрация: 10.01.2013
Сообщений: 16
По умолчанию

Цитата:
Сообщение от lomastr_ Посмотреть сообщение
связывание делается через FOREIGN KEY, если его мало, добавляют признаки..
Как? Поконкретнее можете?

Цитата:
для чего вам еще какието левелы? и длинные юнионы
http://www.opennet.ru/base/dev/hierarchy_sql.txt.html
Цитата:
Одним из вариантов хранения таких иерархий является поуровневое
хранение в различных таблицах. Например, таблица CATALOG_LEVEL_1
хранит все элементы первого уровня вложенности, таблица
CATALOG_LEVEL_2 - второго, и т.д. Ниже приведено описание такой
структуры для случая трехуровневой иерархии.

CREATE TABLE "CATALOG3_LEVEL1" (
"ID" INTEGER NOT NULL PRIMARY KEY,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL
);
CREATE TABLE "CATALOG3_LEVEL2" (
"ID" INTEGER NOT NULL UNIQUE,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL,
"PARENT_ID" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL1"("ID"),
PRIMARY KEY("ID","PARENT_ID")
);
CREATE TABLE "CATALOG3_LEVEL3" (
"ID" INTEGER NOT NULL UNIQUE,
"NAME" VARCHAR(200) CHARACTER SET WIN1251 NOT NULL,
"PARENT_ID" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL1"("ID"),
"PARENT_ID2" INTEGER NOT NULL REFERENCES "CATALOG3_LEVEL2"("ID"),
PRIMARY KEY ("ID", "PARENT_ID", "PARENT_ID2")
);

.........

Получение всех потомков

Довольно часто возникает задача получения всех, в том числе и не
прямых потомков данного элемента. Рассмотрим решение этой задачи для приведенных структур.

структура с потабличным хранением уровней

Потомки данного элемента содержатся в "нижележащих" таблицах и имеют как часть составной ссылки на предка в одном из полей значение ID предка. Общий список потомков можно получить объединением (UNION) запросов.
select "ID",'1' as "LEVEL" from CATALOG3_LEVEL2 where PARENT_ID = 1
union
select "ID",'2' as "LEVEL" from CATALOG3_LEVEL3 where PARENT_ID = 1
Ввод дополнительного поля LEVEL в запрос обусловлен тем, что потомки
элемента в разных таблицах могут иметь одинаковые ID и при объединении запросов вместо нескольких строк в результате будет получена одна. Еще одна проблема, приводящая к необходимости ввода дополнительного поля в запрос, т.к. надо знать, из какой таблицы выбран данный ID.
bidzina вне форума Ответить с цитированием
Старый 29.01.2015, 07:47   #18
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
а как потом их связать?
Огромным запросом. В каждой таблице столько связующих полей сколько таблиц.
Один мой знакомый схитрил. Создал в таблицах поле целочисленное, куда вписывался системный идентификатор таблицы. Брал он его из RDB$ из списка таблиц в БД. Т.е. это тупо уникальный номер таблицы в базе. По нему и строил связь. Запросы конечно получились мудреные но задачу он таким образом решил. Да и работает она по сей день.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 29.01.2015, 09:09   #19
lomastr_
Форумчанин
 
Регистрация: 16.01.2015
Сообщений: 672
По умолчанию

иерархия в таблице это просто
ид, найм, парент ид, ...
вот и вся ваша структура в 1 таблице
чтобы не было совсем каши можно конторы и склады разделить
КОНТОРЫ:ид, найм, парент ид, ...
СКЛАДЫ:ид, найм, парент ид, контора ид,...

или связать через 3 таблицу
КОНТОРЫ:ид, найм, парент ид, ...
СКЛАДЫ:ид, найм, парент ид,...
СВЯЗЬ:контора ид, склад ид

для чего вам левелы? какая у вас задача?

Последний раз редактировалось lomastr_; 29.01.2015 в 09:12.
lomastr_ вне форума Ответить с цитированием
Старый 29.01.2015, 11:28   #20
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
как выдите Parent_ID собраны из всех 3 таблиц и с помощью их невозможно построить DbTree.
т.е. нужны уникальные ключи для всех таблиц (непересекающиеся значения)
00001-10000 первая
10001-20000 вторая
20001-30000 третья и т.д.
решается начальным значением генератора либо триггером insert

или же использовать составной ключ (level, id)
или вычислимое поле "numtable" * 100000 +key

Цитата:
Создал в таблицах поле целочисленное, куда вписывался системный идентификатор таблицы. Брал он его из RDB$
Код:
select 0*100000 +id, name, 0 as parent_id from t1
union
select 1*100000 +id, name, 0*10000+parent_id from t2
union 
select 2*100000 +id, name, 1*10000+parent+id from t3
P.S. конечно же надо "гарантировать" что id всех используемых таблиц не выйдет за границу 1..100000(0..99999)

P.P.S. а единая таблица сразу решает проблему DBTree.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 29.01.2015 в 11:31.
evg_m вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как разработать ИС предприятия? SrgKord Общие вопросы по программированию, компьютерный форум 5 07.02.2014 10:44
Delphi7 - как связывать таблицы hunter08923 Помощь студентам 0 22.05.2012 12:05
ящики не желают падать серг Общие вопросы C/C++ 1 06.12.2010 22:34