Xpoint
   [напомнить пароль]

Структура БД - как правильно?

Метки: [без меток]
2007-03-13 07:53:51 [обр] Майя(0/2)[досье]
Глупый вопрос, наверно. Но поделитесь пожалуйста опытом, кто как делает. Есть предприятия головные, имеющие филиалы, и есть предприятия без филиалов. У каждого предприятия есть его работники. В случае, если предприятие с филиалами - работники привязываются по коду к филиалу. А если филиала нет? Или работник привязывается и по коду филиала, и по коду головного предприятия, и если код филиала 0, значит выбирать по коду головного?
У меня пока сделано так: даже если у предприятия нет филиала, для него создается фиктивный филиал, и по его коду привязываются работники. Но как то мне жалко хранить столько липовых филиалов.
Может быть есть более красивый способ решения подобных проблем?
спустя 12 минут [обр] Дмитрий Попов(0/509)[досье]
Майя[досье]
В такой ситуации, имхо, способ "фиктивного" филиала наиболее правилен. Только изменить чуть-чуть понятие сущности: т.е. филиал должен быть не "фиктивным", а, допустим, "головным". Тогда не будет путаницы, ни с работниками главного офиса филиального предприятия, ни с сотрудниками "нефилиального".
спустя 1 час 45 минут [обр] Thirteensmay(0/157)[досье]
Есть предприятия головные, имеющие филиалы, и есть предприятия без филиалов

Отлично, значит есть таблица organizations с полями id, name, parent и пр. Где id - уникальный идентификатор предприятия, parent - идентификатор родителя этого предприятия (т.е. идентификатор головного предприятия если это филиал, и parent = null/0 если это головное предприятие).

У каждого предприятия есть его работники.

Есть, в таблице employees: id, name, org и пр. Где id - идентификатор работника, org - идентификатор его предприятия (по табл. organizations).

спустя 12 минут [обр] Дмитрий Попов(0/509)[досье]

Thirteensmay[досье]
В большинстве случаев стуктура получится неоправданно запутанной, т.к. для "подсущности" (филиала) требуется описание иных свойств, чем для "сущности" (предприятия). При этом описание предприятия, как мне видится включает опции описания филиала.
Потому выделение в сущность именно филиала мне видится более логичным.

Хотя в любом случае, безусловно, надо знать характеристики и описания конкретно для данной задачи, и мы сейчас больше занимаемся построением предположений.

спустя 34 минуты [обр] Закиров Руслан(0/341)[досье]
Я более склонен к варианту Thirteensmay[досье], а чтобы решить проблему, которую описал Дмитрий Попов[досье], можно использовать несколько таблиц для описания предприятий. В похожей ситуации мы используем центральную таблицу в которой есть id, тип и общие поля для всех типов. Для каждого типа предприятия создана таблица в которой размещенна информация присущая только данному типу, например для филиалов это будет как минимум id головного офиса. Все таблицы разделяют одно поле идентификаторов, то есть не может быть филиала с id равным идентификатору любого другого предприятия. Такая структура позволяет привязать объекты к любому предприятию независимо от типа. Конечно присутствует некая избыточность данных, но я нахожу эту структуру очень гибкой в плане расширения в сторону увеличения типов предприятий.
спустя 31 минуту [обр] Майя(0/2)[досье]
Можно было бы сделать так, как предложил Thirteensmay, но смущает вот что: с точки зрения организации базы основным понятием (или сущностью, как вы называете), является таблица филиалов. К ней привязываются работники и головные предприятия, если они есть.
А вот с точки зрения пользователей программы основной сущностью являются предприятия - независимо от того, имеют они филиалы или нет. Если есть филиал, то выводится список филиалов и работников можно посмотреть по каждому филиалу, но можно и по всем сразу (то есть по головному предприятию). А если филиалов нет, то просто смотрим работников по этому предприятию.
спустя 1 час 10 минут [обр] Сергей Сирик(7/737)[досье]
Тогда:
- таблица просто предприятий
- таблица филиалов
- таблица сотрудников
- таблица связки сотрудник-предприятие
- таблица связки сотрудник-филиал
спустя 20 минут [обр] Thirteensmay(0/157)[досье]

Майя[досье] Похоже Вы нас не поняли. Договорились вот до чего: Нет таблицы филиалов, есть таблица предприятий (организаций), в ней указывается идентификатор организации, ее положение в иерархии (голова или чей то филиал), и дополнительные параметры. Если по разным предприятиям необходимо учитывать разные параметры то выделяем ключ - добавляем в таблицу предприятий указание типа предприятия, и создаем для каждого типа отдельную таблицу в которых и храним эти уникальные параметры. Общие параметры хранятся в таблице предприятий. Приблизительно аналогично поступаем и с сотрудниками. Есть таблица сотрудников, они привязываются к идентификаторам организаций по таблице предприятий. В таблице сотрудников описываем их параметры, если описание сотрудника не едино, а зависит от типа предприятия или еще чегото, то делаем аналогично типам предприятий - т.е. выделяем ключи и создаем отдельные таблицы.

Это в общем случае для большой и гибкой системы. В ваших же конкретных условиях все может быть проще, например не факт что будут нужны типы предприятий и сотрудников, т.к. они могут быть едины, в этом случае обходимся 2 таблицами (см. мой первый пост). В любом случае данный вариант более гибок и не имеет явных костылей типа псевдофилиалов.

В противном случае непонятно что Вас смущает.

P.S. Сергей Сирик[досье] Тогда еще + таблица связки предприятие-филиал. Итого имеем 6 таблиц против 2, только для базового варианта когда параметры предприятий и сотрудников едины. Соответствующая производительность и сложность запросов. IMHO перспективы туманные.

спустя 11 часов [обр] Сергей Сирик(7/737)[досье]

Thirteensmay[досье]
Не, филиал так уж и быть будет нести в себе ИД предприятия :)

итого имеем 6 таблиц против 2, только для базового варианта когда параметры предприятий и сотрудников едины.

Я так понял, когда параметры предприятий и филиалов едины??

спустя 7 часов [обр] Майя(0/2)[досье]
Еще уточнение. Работник привязывается по ключу к предприятию или к филиалу, или к тому и другому?
Если его привязать только к филиалу, а филиал к предприятию конечно тоже привязан, то все хорошо за исключением случая когда у предприятия нет филиала - тогда к чему привязывать работника?
Если привязывать только к предприятию, тогда для предприятия имеющего филиал мы не сможем увидеть список работников одного филиала.
Если привязывать и к тому и другому, то получается таблица Users колонками код работника, имя и так далее, код предприятия, код филиала. Правильно?
Вопрос - не будет ли это избыточностью данных в базе?
спустя 33 минуты [обр] Дмитрий Попов(0/509)[досье]

Майя[досье]
Я все равно считаю, и по Вашим разъяснениям убежадюсь, что вариант предложенный мной наиболее корректен и наименее избыточен.

Тем более, что

  1. "точки зрения организации базы основным понятием, является таблица филиалов"
  2. "А вот с точки зрения пользователей программы основной сущностью являются предприятия"

Вариант с двумя ID для одного работника (ID филиала и ID предприятия) я же искренне считаю сильно избыточным.

З.Ы. Модератору: А не для "Разное::Базы данных" ли эта тема?

спустя 47 минут [обр] Майя(0/2)[досье]
Дмитрий Попов[досье] Можно еще раз подробно про метод, который Вы предложили? Вы предлагаете выделить в сущность филиал. Что это значит более конкретно? Да, будет филиал, головной или неголовной. Если он головной - то он равносилен головному предприятию. Если он неголовной - у него есть родитель. Как будет связан работник филиала с родителем?
спустя 17 минут [обр] Дмитрий Попов(0/509)[досье]

Майя[досье]
Не равносилен головному предприятию.

Все немного, но наоборот:
Есть филиалы. У них есть статус (головной/неголовной). Для всех филиалов есть родитель - предприятие.
Если у предприятия больше одного филиала(офиса), то и филалов много.
Сотрудник связан с филиалом. Соответственно через связь сотрудника с филиалом и филиала с предприятием сотрудник связан и с предприятием, благо эта выборка делается одним несложным и достаточно быстрым запросом.

Если у предприятия один филиал, то просто на клиенте выводим предприятие как "без филиалов" (хотя не факт, что если подумаете, получится, что и это нужно)

Плюсы такого подхода:

  1. Прозрачная структура с четкими, не дублирующимися связями.
  2. В случае если предприятие не имело филиалов, а потом открыла представительство, допустим, в другом городе - не требуется изменений существующих данных.

Подход Сергей Сирик[досье] мне не нравится именно дублированием связок:
- сотрудник-предприятие
- сотрудник-филиал
Т.е. получается, что если у предприятия не было филиала, а потом он появился, или если по какой-то причине необходимо изменить связь филиала с предприятием (грубый пример: поглощение одной компанией другой), то это потребует изменения всех ссылок на предприятия всех сотрудников всех филиалов.

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

спустя 1 час 12 минут [обр] Дмитрий Кучкин(0/236)[досье]
IMHO, Thirteensmay[досье] все-таки предложил самую простую, понятную и, главное, легко расширяемую схему.
Например, в нее легко укладывается и понятие "фиктивного" филиала. Ему соответствует запись в таблице филиалов (или предприятий - назвать можно как угодно) с parent is null.
спустя 47 минут [обр] Thirteensmay(0/157)[досье]

Дмитрий Кучкин[досье] Parent is null это и есть "фиктивный филиал" в идеологии Майя, т.е. предприятие. Все ненуловые паренты - офисы ;)

Сдается мне что тема как раз будет в "Анализ и проектирование" к Сергей Сирик[досье]:

Я так понял, когда параметры предприятий и филиалов едины ?

Да хоть предприятий, хоть филиалов, хоть сотрудников, все может быть, тут этого еще никто не понял, Майя[досье] молчит как партизан. Майя[досье] скажите пожайлуста у Вас описания предприятий/филиалов/сотрудников все одинаковые ? Или например для одного предприятия или сотрудника перечень параметров один, а для другого - другой ?

Майя[досье]:

Работник привязывается по ключу к предприятию или к филиалу, или к тому и другому ?

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

Повторю еще раз, структура элементарная: 2 таблицы: организации и работники:
1 - organizations: id, name, parent...
Где: id - идентификатор организации, parent - идентификатор родителя этой организации (т.е. идентификатор головного предприятия если это филиал, и parent = null/0 если это головное предприятие).
2 - employees: id, name, org...
Где: id - идентификатор работника, org - идентификатор его организации.

Майя[досье], Дмитрий Попов[досье] Нет тут никакой избыточности, да в принципе получается практически тоже самое что и Вы сами предлагаете, только Ваша таблица филиалов здесь называется таблицей организаций, и вместо признака "организация или филиал организации" используется более гибкое понятие parent, за счет чего появляется возможность выстаивать многоуровневые иерархии.

Классический пример: Предприятие Рога и копыта Российской Федерации имеет филиалы в г. Москва и Ростов, при этом у филиала в Москве есть доп. офис в кремле. Соответственно в БД имеем:
organizations: (id, name, parent):
1, Рога и копыта РФ, null;
2, Рога и копыта Москва, 1;
3, Рога и копыта Ростов, 1;
4, Рога и копыта Кремль, 2;
employees: (id, name, org):
1, Иванов И.И., 1;
2, Петров П.П., 2;
3, Сидоров С.С., 2;
и т.д.

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

спустя 42 минуты [обр] Майя(0/2)[досье]
Судя по последнему посту Thirteensmay[досье] вы предлагаете разместить филиалы и предприятия в одной таблице? Наверно вы это сразу имели в виду, да я не сразу поняла. Как то я совсем забыла про этот замечательный способ создания иерархической структуры.
Спасибо большущее!!
Кажется до меня дошло наконец, как надо организовать БД
СПАСИБО ВСЕМ еще раз!!!
спустя 5 минут [обр] Майя(0/2)[досье]
Еще вопрос - а можно ли так делать из соображений сохранения целостности данных и правильной организации БД?
Цикличность данных придется отслеживать самим?
спустя 2 минуты [обр] Дмитрий Попов(0/509)[досье]

Thirteensmay[досье]

 да в принципе получается практически тоже самое что и Вы сами предлагаете, только Ваша таблица филиалов здесь называется таблицей организаций, и вместо признака "организация или филиал организации" используется более гибкое понятие parent, за счет чего появляется возможность выстаивать многоуровневые иерархии.

Вот именно. Вопрос: Зачем здесь эта возможность многоуровневых иерархий? "что бы было"? Я столько раз помню, когда вот подобные "универсальные" решения приводили к очень печальным результатам, что боюсь их как огня.

скажите пожайлуста у Вас описания предприятий/филиалов/сотрудников все одинаковые ? Или например для одного предприятия или сотрудника перечень параметров один, а для другого - другой ?

Я считаю, вопрос не верно поставлен, но пусть Майя ответит на него, но и на мой, более критичный для организации базы:
Майя, скажите самый главный момент, которые мне не понятен сначала, и не понятен до сих пор:

  1. Описание предприятия и головного филиала отличается от описания филиала? Если отличается то чем?

Я повторюсь, почему считаю свою сруктуру более правильной: Сколько я помню подобных баз (работающих именно с сущностью предприятие-филиал) - все основные описания относятся только к предприятию. А у филиала минимум параметров, характеризующих только филиал.
И я не вижу смысла создавать таблицу филиалов, если в ней 30 полей описания, которые нужны только в 20% случаев (головного предприятия).

Вы забываете, что там будет не три поля, а десятки, потому что какие-то общие поля не выносят в отдельную таблицу (и глупо выносить)

спустя 1 минуту [обр] Дмитрий Попов(0/509)[досье]

Майя[досье]
Да, цикличность будете отслеживать сами, убивать потомков сами.

Ответьте, пожалуйста, на заданный мной выше вопрос.

спустя 34 минуты [обр] Майя(0/2)[досье]
Описание головного конечно отличается от описания филиала набором параметров. У головного есть ИНН, директор и так далее - очень много всего, это организация с которой заключаются договора. Филиалы же имеют название и местоположение (город) - и все. Они нужны только чтобы знать откуда пользователь.
спустя 6 минут [обр] Сергей Сирик(7/737)[досье]
сообщение промодерировано
М Уговорили :)
Перенесено из форума "Программирование::Теория и алгоритмы"
спустя 46 секунд [обр] Майя(0/2)[досье]
Дмитрий Попов[досье] я правильно понимаю, что по Вашему мнению надо сделать следующие таблицы:
orgs1 (ido1,name,inn,director,...)
orgs2(ido2,ido1,name,town)
users(idu,ido2,fio,tel,...)
где orgs1 - головные предприятия
orgs2 - филиалы
users - пользователи филиалов
спустя 4 часа 38 минут [обр] Закиров Руслан(0/341)[досье]

Так чтобы не вводить в заблуждение кого либо, я объясню свой вариант со схемами.
Вводим таблицу OrganisationUnit с id, Type и общими полями для всех типов подразделений, будь то головной офис, филиал, холодинг или компания в составе холдинга. Добавляем по таблице для каждого типа: Branches, Headquarters... что-то в этом духе. В каждой такой таблице, только дополнительная информация по объекту. Например в таблице Branches должно быть поле Headquarter. Фактически вариант Thirteensmay[досье], но только поля имеющие значение для все типов в одной таблице, а специфика типа в другой.

Для того чтобы не вводить ссылку на OrganisationUnit в каждой таблице, используется трюк с общим генератором ID. В зависимости от БД реализуется по разному, но суть в том что сначала создаем OU с уникальным ID, а потом вставляем запись с этим ID в нужную таблицу, описывающую ваш тип OU. Такой трюк еще позволяет делать ссылки как на OU так и на конкретный тип unit'а не боясь получить неясность.

Я не утверждаю, что такой вариант идеальный, но он гибкий, расширяемый и без больщой избыточности информации. Все зависит от того, что вы хотите получить. Обычно люди хотят ускорить запросы или сделать структуру гибче, но реже уменьшить объем данных.

спустя 1 минуту [обр] Кирилл [Kirk] Королев(0/673)[досье]
Сергей Сирик[досье] а связь Предприятие-Филиал, красоты ради? =)
Майя[досье] пользуйте вариант от Thirteensmay[досье] "Устрашающая" цикличность обходится тривиально, в особенности если по логике требуется только два уровня.
спустя 6 часов [обр] Сергей Сирик(7/737)[досье]

Кирилл [Kirk] Королев[досье]
Не, это таки избыточно :) Связки по сотрудникам могут оччень пригодиться, когда попросют сделать историю переходов сотрудников между филиалами :) А филиалы между предприятиями - эт врядли.

Майя[досье]
В общем-то Вам описали большинство возможных вариантов ... т.е. будет из чего выбирать, когда (если :) выбранная структура окажется неподходящей. Они все не идеальны, и грабли могут вылезти любые и обычно неожиданно ... В частности, из-за особенностей реалиации в тех или иных СУБД, от объема данных и т.д. Так например запрос на вывод всех предприятий из таблицы, описывающей только предприятия - это простейший запрос. А тот же запрос из иерархической таблицы - это уже запрос с условием, из на несколько порядков бОльшей таблицы.
Т.е. в ряде случаев схема с простой структурой будет медленней ... из-за простоты структуры. В других случаях - сложная будет тормозить ... уже из-за сложности.

Хорошо бы еще знать потенциальные объемы таблиц и СУБД :)

спустя 8 часов [обр] Майя(0/2)[досье]
Объемы такие: всего предприятий будет около 2000. Филиалы имеют только около 100. Кол-во филиалов у таких предприятий от 3 до 50. Пользователей в филиале может быть от 10 до 500, на головном предприятии от 10 до 4000.
Но с каждым пользователем еще связаны услуги. А с услугами их стоимость. В итоге должны получиться выборки по стоимости обслуживания предприятия в целом, независимо от того имеет оно филиалы или нет - с разложением по используемым каждым пользователем услугам.
спустя 14 часов [обр] Сергей Сирик(7/737)[досье]
Ага, ну на таких объемах структура не сильно важна, если честно. Что так, что так будет работать. Т.е. выбирайте, что наиболее Вам симпатично - и вперед :) Для опыта так или иначе пригодится.
спустя 3 дня [обр] Майя(0/2)[досье]
Понятно. Всем большое спасибо за советы!
спустя 1 месяц 4 дня [обр] Денис Бесков-Доронин[досье]

Для проектирования типовых структур предлагаю смотреть "Шаблоны анализа" Фаулера, там много всего хорошего. В частности, в вашем случае, Organization Structures (Accountability).

Эта тема была бы значительно более короткой, если бы

  1. Автор исходного сообщения привёл:
    1. атрибутивное и структурное текстовое аналитическое описание предметной области;
    2. функциональные и нефункциональные требования.

(моя методичка для студентов по моделированию предметной области)

  1. Прочие отвечающие использовали:
    1. диаграммы модели или хотя бы примеры таблиц, благо у форума такая функциональность есть;
    2. примеры запросов, отвечающих функциональным требованиям.
Powered by POEM™ Engine Copyright © 2002-2005