vyshkant
@vyshkant
developer

Как канонично организовать структуру таблиц в базе данных MySQL?

Добрый день!

Меня интересует вопрос того, как правильно организовать структуру таблиц в базе данных MySQL, если с её помощью надо описать следующую условную ситуацию:

Есть некоторое число работников. Работник может работать, а может не работать. Если работник работает, значит должен быть указан завод, на котором он работает, а также цех, в котором он работает.

Есть некоторое число заводов, однако не все из них подразделяются на цеха.

Вопрос: какие должны быть созданы таблицы и какие должны быть связи между ними.

Самое незамысловатое решение, конечно же, это создать таблицу работников:
CREATE TABLE `worker` (
  `id` INT UNSIGNED NOT NULL ,
  `plant_id` INT NOT NULL,
  `department_id` INT NOT NULL
) ENGINE = InnoDB;


таблицу заводов:
CREATE TABLE `plant` (
  `id` INT UNSIGNED NOT NULL
) ENGINE = InnoDB;


и таблицу цехов:
CREATE TABLE `department` (
  `id` INT UNSIGNED NOT NULL,
  `plant_id` INT NOT NULL,
) ENGINE = InnoDB;


Однако данное решение содержит ряд неприятных моментов:
  • неработающий работник будет содержать в себе plant_id = NULL, department_id = NULL (хотя второе прямо вытекает из первого)
  • работник, работающий на заводе, где нет цехов, будет содержать в себе department_id = NULL (хотя, по большому счету, это свойство целого завода, а не конкретного работника)
  • работник, работающий на заводе, где есть цеха, буде содержать в себе plant_id = x, department_id = y, а в это же время в таблице department будет id = y, plant_id = x (т.е. будет некоторая избыточность)
Могли бы посоветовать каноничный, наиболее нормализованный и эталонный вариант решения данной задачи?

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

Спасибо.
  • Вопрос задан
  • 561 просмотр
Решения вопроса 1
pi314
@pi314
Президент Солнечной системы и окрестностей
Вот Вам пример сильно нормализованной модели под заявленные хотелки (насколько я их понял).
e480bdfe4acd4f2c9887ed7f6970beb6.png
SET FOREIGN_KEY_CHECKS=0;

CREATE TABLE department
(
	id INT NOT NULL,
	name VARCHAR(50) NOT NULL,
	PRIMARY KEY (id)
) 
;
CREATE TABLE department_property
(
	department_id INT NOT NULL,
	property_id INT NOT NULL,
	UNIQUE KEY UQ_department_property_department_id_property_id(department_id, property_id)
) 
;
CREATE TABLE employment
(
	id INT NOT NULL,
	worker_id INT NOT NULL,
	plant_id INT NOT NULL,
	PRIMARY KEY (id),
	UNIQUE KEY UQ_employment_worker_id_plant_id(worker_id, plant_id)
) 
;
CREATE TABLE employment_department
(
	employment_id INT NOT NULL,
	department_id INT NOT NULL,
	UNIQUE KEY UQ_employment_department_employment_id_department_id(employment_id, department_id)
) 
;
CREATE TABLE plant
(
	id INT NOT NULL,
	name VARCHAR(50) NOT NULL,
	PRIMARY KEY (id)
) 
;
CREATE TABLE property
(
	id INT NOT NULL,
	name VARCHAR(50) NOT NULL,
	value VARCHAR(50) NOT NULL,
	PRIMARY KEY (id)
) 
;
CREATE TABLE worker
(
	id INT NOT NULL,
	name VARCHAR(50) NOT NULL,
	PRIMARY KEY (id)
) 
;
SET FOREIGN_KEY_CHECKS=1;

Но, как уже сказали, нормализация не является самоцелью! С запросами к этой модели у программиста уже возникнет некоторая Камасутра, а будут ли они оптимальны по перформансу - вообще отдельная тема. Так что, не устану повторять: оптимизация структуры БД заключается не в достижении максимально возможной NF, а в том, чтоб на ней оптимально выполнялись именно те запросы, которые на ней должны выполняться ))
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@LiguidCool
Учитесь селектить Join'ы. База самая обычная один-ко-многим, ничего в ней нет. Bull вполне допустим, если вписывается в вашу логику.
Ответ написан
Комментировать
sim3x
@sim3x
МестоРаботы:
  тип = (завод, цех, )
  вышестоящее_место_работы = FK(МестоРаботы)

Работник:
  место_работы = FK(МестоРаботы)


но в коде придется правильно сохранять, чтоб цех не содержал заводов
Также будут проблемы если у заводов и цехов сильно различаются поля
Ответ написан
Комментировать
Smithson
@Smithson
20+ лет админю
Вопрос про нормализацию - вы пытаетесь байты экономить или хотите сделать всё по фен-шую?
Учтите, что с полностью нормализированными базами трудно работать человеку, обычно логика так не поворачивается, как там надо.
Так что отталкивайтесь от разумной оптимизации, когда ни у программиста, ни у DBA, ни у пользователя при работе с такой базой не идет кровь из глаз.

Ваш вариант, кстати, вполне нормален, повесить триггеры, чтобы отслеживать события удаления заводов, цехов, переезда цехов из завода в завод и перевода работников - и всё будет вполне терпимо.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
22 нояб. 2024, в 00:55
500 руб./за проект
21 нояб. 2024, в 23:30
300000 руб./за проект
21 нояб. 2024, в 22:21
3000 руб./в час