Russian Qt Forum
Ноябрь 27, 2024, 17:53 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: структура БД и связь "Многие-ко-многим"  (Прочитано 11040 раз)
Karl-Philipp
Гость
« : Январь 28, 2010, 13:16 »

разрабатываю базу данных для предприятия:
На предприятии есть машиностроительный цех со станками.
Существует перечень заданий (изделий), которые надо выполнить (произвести). Каждое задание состоит из определенного перечня операций. Каждая операция может быть выполнена на определенных (разных) станках.
1. Оцените, пожалуйста, правильно ли спроектирована структура БД? (см вдложение)
2. Как усматривается из структуры БД, мне необходимо будет связывать таблицы, содержащие связи "Многие-ко-многим". Подскажите, пожалуйста, поддержиавает ли Qt, в частности, с помощью QSqlRelationalTableModel и QSqlRelationalDelegate такую возможность?

upd
добавил в табличке operation2task поле machineId и связал его с machine2operation
« Последнее редактирование: Январь 28, 2010, 14:29 от terlan » Записан
asvil
Гость
« Ответ #1 : Январь 28, 2010, 17:42 »

1. Правильно.
2. Поддерживают, а точнее им без разницы. Делегат и модель никак не контролируют вводимое значение. Это дела sql-сервера.
Другое дело что внешний ключ состоит из двух столбцов, если я правильно понял. Значит надо вешать два делегата.

sql запрос делегата на столбце operation2task.machineId должен быть таким
select title from machine2opertaions join machines on machineId = id.

sql запрос делегата на столбце operation2task.opertaionId должен быть таким
select title from machine2opertaions join operations on operationId = id AND machineId = CURRENT_ROW.machineId.

где CURRENT_ROW.machineId - это значение ячейки operation2task.machineId.
Необходимо ловить currentRowChanged и dataChanged вьюшки и модели и в них менять sql запрос на втором делегате.

Все вышеназванные выкрутасы sqlrelational{.*} не поддерживают.
Для данной структуры надо делать своих combobox делегатов, которые умеют заполнять себя из sql запроса.
Прикрепил нужного делегата.
Записан
Karl-Philipp
Гость
« Ответ #2 : Январь 29, 2010, 08:56 »

asvil, спасибо большое Улыбающийся
Ответ тянет на статью. Разберусь - могу оформить в вики, если вы и админы не против.
Записан
crossly
Гость
« Ответ #3 : Январь 29, 2010, 13:03 »

не могу понять назначение таблицы machine2operation .....
Записан
Karl-Philipp
Гость
« Ответ #4 : Январь 29, 2010, 13:21 »

не могу понять назначение таблицы machine2operation .....
иными словами "станок для операции". То есть одна операция может быть выполнена на разных станках Улыбающийся
Записан
asvil
Гость
« Ответ #5 : Январь 29, 2010, 22:03 »

Я не прав. Я думал станок поддерживает определенный набор операций.
Получается task зависит в первую очередь от операции.
Я бы переформировал структуру.

opertaion2task.operationId (n->1) operations.id
operation2task.machineId (n->1) machines.id

operation2machine.operationId (n->1) operations.id
operation2machine.machineId (n->)machines.id

sql запрос на opertaion2task.operationId
select title from operations;
sql запрос на opertaion2task.machineId
select title from machines join operations2machines on id = machineId AND operationId = CURRENT_ROW.operationId.

Но при такой схеме sql сервер не будет контролировать логику и для таска может оказаться несовместимая пара станок - операция.
Вообщем-то так сходу правильно ответить не могу.

В реальности как обстоят дела? Сколько операций поддерживает станок? Сколько станков поддерживают одну операцию? ....в среднем.
« Последнее редактирование: Январь 30, 2010, 14:00 от asvil » Записан
Karl-Philipp
Гость
« Ответ #6 : Январь 29, 2010, 22:21 »

Мне кажется, что с самого начала вы таки правильно поняли. Один станок - одна операция. Например сверлильный станок - сверлильная операция. Токарный станок - токарная операция (точение, шлифование), но все называется токарная операция, фрезеровочный станок - фрезеровочная операция.
Другое дело, что станков одного вида может быть несколько, поэтому
не могу понять назначение таблицы machine2operation .....
иными словами "станок для операции". То есть одна операция может быть выполнена на разных станках Улыбающийся
то есть на станках одного и того же вида имелось в виду Улыбающийся
Записан
crossly
Гость
« Ответ #7 : Январь 29, 2010, 22:48 »

а нельзя ли слегка абстрагироваться ... или жизненно важно на каком именно станке и в каком углу он стоит??
Записан
Karl-Philipp
Гость
« Ответ #8 : Январь 29, 2010, 23:19 »

думаю, что важно Улыбающийся

для программы будет использоваться "оптимизатор", который должен распределять (назначать) операции по станкам. Тут уже, как мне кажется, важно, в каком углу стоит станок, что на нём будет произведено, в какой период времени это может быть произведено.
(некоторые поля из таблиц я убрал с целью локализации задания, видать зря Улыбающийся )
Записан
asvil
Гость
« Ответ #9 : Январь 30, 2010, 14:24 »

Тогда давайте заново. Я переосмыслил, и пришел к другому выводу.
Один станок - одна операция. Такие слова обязывают нас сделать таблицу.
------------------------
machines.id (bigserial)
machines.machineTitle (text, eg сверл станок инв № 123)
machines.operationTitle (text, eg сверлеж ГОСТ 12551)
------------------------
слова
Цитировать
одного вида может быть несколько
в свою очередь обязывают сделать
---------------------------
machines.typeId  (integer fk (n->1)types.id)
---------------------------
-------------------------
types.id (serial)
types.title (text eg Сверлеж )
-------------------------
Цитировать
распределять (назначать) операции по станкам.
Вот здесь я бы переформировал (вставлю модное слово) бизнес-логику. Я считаю Вам необходимо распределять станки по таскам. Чтобы распределять станки по таскам делаем
------------------------------
task2machine.taskId (integer fk (n->1) tasks.id)
task2machine.machineId (делегат SELECT id, ARRAY[machineTitle, '  ', operationTitle] FROM machines)
------------------------------

В этой версии ответа я не учел строгая ли последовательность выполнения операций в таске. И вообще сколько операций в таске?

П.С. я неподходящего делегата скинул. Отлажусь и скину делегата с n кол-вом столбцов, в котором необходимо будет задавать ключевую колонку и дисплейную.
Записан
Karl-Philipp
Гость
« Ответ #10 : Январь 30, 2010, 18:32 »

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

Таблицу operations убрал, так как types уже уточняет, что будет делаться на данном станке.

Цитировать
В этой версии ответа я не учел строгая ли последовательность выполнения операций в таске. И вообще сколько операций в таске?
Да, последовательность выполнения операций для задания (таски) важна. Поэтому ввел в таблицу task2machine поле machineOrderIdx.
Операций в таске может быть от 1ой до, например, 20, может чуть больше.
Записан
asvil
Гость
« Ответ #11 : Январь 30, 2010, 19:04 »

operationTitle необходимости нет.
Итак, схема есть.
Прикрепил нужного делегата.

Пример использования
Код:
GridDeleagate *forms_delegate = new GridDelegate("machines", "id", "machineTitle", this);
forms_delegate->setConnection(QSqlDatabase::defaultConnection);
forms_delegate->setQuery("SELECT id, machineTitle FROM machines;");
// Этой строкой указываем, какому ключевому столбцу соответствует дисплейный столбец.
forms_delegate->addLink(0, 1);
// Где-нибудь назначаем делегата.
setItemDelegateForColumn("task2machine", forms_delegate);
Или таблицы нечеловек будет заполнять? Ну вообщем, не важно.
Записан
Karl-Philipp
Гость
« Ответ #12 : Январь 31, 2010, 13:40 »

Цитировать
Или таблицы не человек будет заполнять? Ну вообщем, не важно.
На начальном этапе будет заполнять человек, в перспективе планируется использовать планировщик, хотя вмешательство человека также не будет исключаться Улыбающийся

Спасибо большое за участие и за классы. Работаю!
« Последнее редактирование: Январь 31, 2010, 14:07 от terlan » Записан
Karl-Philipp
Гость
« Ответ #13 : Февраль 01, 2010, 01:18 »

asvil,

расскажите, пожалуйста, что за макрос DECLARE_SCRIPT_PROXY_FUNCTIONS(GridDelegate)?
По всей видимости он находится в файле #include "scriptfactory.h", но последнего в архиве не было.
Попробовал закомментировать макрос и инклюд - появилась ошибка "невозможно найти функцию formatFieldValue(value) (строка 229, griddelegate.cpp)"

Помогите разобраться, пожалуйста Улыбающийся
« Последнее редактирование: Февраль 01, 2010, 19:01 от terlan » Записан
Karl-Philipp
Гость
« Ответ #14 : Февраль 01, 2010, 23:24 »

Значит была создана функция:
Код
C++ (Qt)
QString formatFieldValue(const QVariant& v)
{
   QString res = "";
   switch(v.type())
   {
   case QVariant::Bool:
       res = v.toBool() ? "true" : "false";
       break;
   case QVariant::Int:
       res = QString("%d").arg(v.toInt());
       break;
   default:
       res = "";
   }
   return res;
}
продолжение следует Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.074 секунд. Запросов: 21.