|
Вопрос # 3 372/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты!
Есть две таблицы Таб1 иТаб2. У Таб1 поле "Приход", у Таб2 поля "Наличие"и "Факт". Как осуществить с помощью SQL запроса суммирование полей "Приход" и "Наличие" и отобразить результат в поле "Факт"?
 |
Вопрос задал: timkit (статус: Посетитель)
Вопрос отправлен: 6 ноября 2009, 05:59
Состояние вопроса: открыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 19; последнее сообщение — 10 ноября 2009, 12:27; участников в обсуждении: 2.
|
Егор (статус: 10-ый класс), 7 ноября 2009, 23:45 [#1]:
не совсем корректно спроектирована база
или я чего-то не так понял 
подробнее бы. расписать бы немножко содержимое обеих таблиц.
типа, таблица Таб1:
id Приход Дата
1 154 12.10.09
2 200 13.10.09
...
таблица Таб2:
id Наличие Факт
1 574 ???
2 0 ???
...
если это примерно так, то, в общем случае, провести суммирование невозможно, поскольку непонятно, какую строку с какой суммировать (первую из первой таблицы + первая из второй или восьмая из первой + 10-я из второй)
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 05:35 [#2]:
Да, таблицы имеют именно такую структуру. Придется наверно переносить поле "Факт" в Таб1
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 05:48 [#3]:
По-хорошему, в Таб1 нужно переносить не Факт, а Наличие. а поле Факт вообще убрать - вычислять его при запросах, потому что само наличие поля Факт говорит об избыточности (есть данные, которые мы можем спокойно вычислить, а мы их храним), чего в реляционных базах данных стараются всеми избежать.
если же нужно оставить две таблицы (тогда поясните, зачем), то ситуацию тоже можно решить, но вот с суммированием строк будет заморочка.
всё дело в том, что в реляционных базах данных нет понятия "первая строка", "вторая строка", "n-я строка" или "последняя строка". поэтому в общем случае невозможно определить какую строчку от какой нужно вычитать. а что, если количество строк в одной таблице не совпадает с количество строк в другой?
НО! если в таблицах есть id и он один и тот же для Таб1 и Таб2, то тут уже можно что-то сделать.
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 06:28 [#4]:
Для большей наглядности представляю структуру обоих таблиц:
Поля Таб1 - ID, Num, Material, Limit, Ostatok, Fakt
Поля Таб2 - ID, Num, Material, Prixod, Data, Instancer
При занесении данных в Таб1 поле Num (int) заполняется инкрементом т.е. при каждом "INSERT" происходит Num:=CLientDataset.Datasource.DataSet.RecordCount+1, таже заполняюся поля Material,Ostatok, Limit. Одновременно в таблицу Таб2 в поле Num вставляется запись со значением "1" (чтобы идентифицировать запись как соответсвующую записи из Таб1), в поле Material - материал, как в Таб1, Data и т.д.
При заполнении Таб2 поле Num аналогично заполняется инкрементом, но заполняется только поле Instancer,Prixod,Data.
Теперь при всем этих действиях (Заполненных полях Ostatok из Таб1 и Prix из Таб2, должно произойти суммарование всех записей поля Prix и значения из Ostatok).
Каряво, не спорю.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 06:56 [#5]:
УЖАСНО!
сведите обе таблицы в одну!
уберите поле Num нафиг - оно не нужно - зачем вам тогда поле id? вот пусть id и выполняет функции Num
здесь нарушаются главные требования к реляционным базам данных - данные представлены в ненормализованном виде, т.е. дублируются, повторяются, имеется избыточность.
ещё раз пишу:
1. обе таблицы свести в одну
2. убрать поле Num, а вместо него использовать ID
3. убрать поле Fakt, вычислять его при каждом обращении к базе
либо опишите, почему была выбрана такая структура и обоснуйте её
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 07:00 [#6]:
или я чего-то не понял?
вы уж опишите задачу полнее - что дано, что надо сделать, а то я так чувствую, что база изначально была спроектирована неверно, нет чёткого понимания, что нужно (и как) хранить в базе.
соответственно ищется ответ не на тот вопрос
таблица 1 для чего? что в ней должно храниться? данные по материалу? или данные по приходу?
таблица 2 для чего? в ней хранятся данные по расходу?
и по именам - называть таблицы "Таб1" и "Таб2" - это... мягко говоря, некорректно. такое именование не даёт никакого представления о том, что хранится в таблицах
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 07:29 [#7]:
Поле ID в данном случае - это поле которое в свою чередь является идентификатором для ссылки на другую таблицу - "Объекты", поэтому оно и присутствует.
Егор, если Вам не трудно прочтите следующее, может Вы предложите лучшую структуру или действительно свести все в одну таблицу.
Суть программы следующая:
Имеется дерево со списком предприятий у каждого предприятия свой дочерний узел - изделие. Каждое изделие имеет свой уникальный ID. В соответствии с этим ID в Таблицу "Материалы" заносятся данные.
Например:
ID Num Материал Остаток,кг Лимит, кг Факт, кг
-----------------------------------------------------
1 1 Труба 32 100 1000 800
1 2 Лист 140 500 340
1 3 Швеллер 500 100 100
В таблицу "Материал заменитель"
заносим теже ID и Num для идентификации среди других объектов и материалов соответственно. Таблица "Материал заменитель" содержит обязательно первую запись со строкой из Таблицы "Материалы" т.е. изначальный материал, а потом добавляются материалы заменители, если невозможно купить исходный материал. Поле ID_self - внутренний счетчик
ID Num Id_Self Материал Заменитель Приход,кг
------------------------------------------------
1 1 1 Труба 32 - 400
1 1 2 - Труба 36 700
В таблицу "Материал заменитель" я заношу приход материала, а в поле "Факт" я хотел отображать сумму того, что есть на складе т.е. значение из поля "Остаток" и значение из поля "Приход". Если заменитель присутствует то в сумму пойдет значение поля "Приход" именн для заменителя. Вот и все.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 08:59 [#8]:
мда, задачка...
т.е., я так понял, на складе есть материалы разных предприятий. также можно менять материалы (т.е. имеются данные по тому, какое изделие каким можно менять)
так?
кхм...
тогда я бы спроектировал по-другому. выделил бы таблицу "материалы" и вынес туда все-все материалы:
id firm_id material
----------------------
1 1 Труба 32
2 1 Лист
3 1 Швеллер
4 1 Труба 36 <--- перенёс из заменителей!
...
id - собственный номер материала
firm_id - номер предприятия
затем сделал бы таблицу "материалы-заменители", в которой описал бы, как можно менять материалы:
id_base id_replace
---------------------
1 4 <----- т.е. материал с id=1 (Труба 32) можем заменить материалом с id=4 (Труба 36)
...
а вот дальше - это уже чуть подробнее знать надо, что же вы в базе храните, вернее, с какой целью хотите данные использовать. если это просто данные по хранению (типа, склад) - это одно, если нужно составлять смету на строительство - это другое, если задача в чём-то другом - нужно третье решение.
кстати, а поле "лимит" - оно зачем?
ps просьба - таблицы оформляйте с помощью тегов {{ code }} {{ /code }} чтобы структура их была понятнее
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 09:26 [#9]:
Вообще эти две таблицы только часть программы. Суть ее заключается в следующем:
Как я уже писал, есть список объектов (Заказчиков) и входящих в него изделий, каждое изделие в свою очередь состоит из отдельных деталей, но детали не обозначаются, а обозначаются материалы, из которых они сделаны. В силу некоторых причин (отсутствие у поставщика или его удаленность) материал необходимо заменить аналогом (что и предполагалось делать во 2-ой таблице). Причем не факт, что замена произойдет один раз. Самое главное в программе - строгий учет (с привязкой к конкретной дате).
Почему я не сделал все в одной таблице? Потому как хранить все в одной куче показалось мне не совсем удобным, да и запросы слишком громоздкие получаться. Я решил сделать отношение таблиц по принципу "один ко многим".
Так то все нормально работает, но единственное, что вызвало затруднения, это вычисляемое поле "Факт"(фактическая масса материала в наличии). Кстати в поле "Лимит" заносятся данные о конечном, необходимом количестве материалов на изготовление.
Сама таблица "Материалы" тоже предполагает редактирование (не всегда человек может ввести правильные данные), но при изменении материала в таблице "Материалы" соответствующая запись должна измениться и в таблице "Замена материалов".
Ну вот в принципе и вся суть этой части программы.
P.S. Очень много хлопот доставило то, что БД работает удаленно, и клиентов несколько.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 12:17 [#10]:
что-то я запутался 
а что в поле факт надо хранить?
а если заменителей несколько, как тогда вычислять? или заменителей не может быть несколько - всегда только один или ни одного?
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 12:25 [#11]:
>> См. выше. В таблицу "Материал заменитель" я заношу приход материала, а в поле "Факт" я хотел отображать сумму того, что есть на складе т.е. значение из поля "Остаток" + значение из поля "Приход". Если заменитель присутствует то в сумму пойдет значение поля "Приход" именно для заменителя.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 13:03 [#12]:
а заменитель один?
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 13:06 [#13]:
Не обязательно, может быть и несколько. Вообще редко возникают ситуации, что больше одного, но все же такую возможность включить нужно.
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 13:21 [#14]:
а тогда как быть? что в факт заносить?
и очень хорошо бы пример привести - записи в первой таблице, записи во второй, что должно быть в поле факт.
а то я так толком и не понял, если честно
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 13:36 [#15]:
Если заменитель присутствует то в сумму (т.е. в поле "Факт") пойдет значение поля "Приход" именно для заменителя (если их несколько то значение берется для последнего по дате заменителя).
|
|
Егор (статус: 10-ый класс), 9 ноября 2009, 13:47 [#16]:
тэкс... т.е. нам ещё одно поле вводить надо - время занесения записи. так получается?
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 9 ноября 2009, 19:46 [#17]:
Добавлять не надо, оно уже есть.
|
|
Егор (статус: 10-ый класс), 10 ноября 2009, 10:01 [#18]:
тогда я вижу только один способ - программно заполнять это поле, т.е. читаем из таблицы материалов-заменителей нужную запись, а затем вычисляем нужное значение для поля факт
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
timkit (статус: Посетитель), 10 ноября 2009, 12:27 [#19]:
Спабо большое Егор за содействие!
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|