![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Формирование SQL-запроса [D6, IB6.x]
me2 © (2003-06-12 17:33:00)Имеются пять таблиц:
1. MATERIALS - справочник материалов с полями
material_code - уник. код
material_name - наименование
...
2. IN_MATERIALS - журнал операций прихода с полями
operation_code - уник. код операции
operation_date - дата операции
...
3 IN_MATERIAL_ITEMS - перечень материала в каждой операции с полями
operation_code - ссылка на IN_MATERIALS."operation_code"
material_code - ссылка на MATERIALS."material_code"
quantity - количество пришедшего материала
4. OUT_MATERIALS - журнал операций расхода с полями
operation_code - уник. код операции
operation_date - дата операции
...
5. OUT_MATERIAL_ITEMS - перечень материала в каждой операции с полями
operation_code - ссылка на OUT_MATERIALS."operation_code"
material_code - ссылка на MATERIALS."material_code"
quantity - количество пришедшего материала
Хочу получить выборку материалов, которые участвовали в операциях прихода/расхода с остатком на некоторое число. Делаю
так
select MATERIALS."material_name",
sum(IN_MATERIAL_ITEMS."quantity") -
sum(OUT_MATERIAL_ITEMS."quantity")
from
MATERIALS, IN_MATERIAL_ITEMS, OUT_MATERIAL_ITEMS, IN_MATERIALS, OUT_MATERIALS
where
(MATERIALS."material_code" = IN_MATERIAL_ITEMS."material_code") and
(MATERIALS."material_code" = OUT_MATERIAL_ITEMS."material_code") and
(IN_MATERIALS."operation_date" like ("12.06.2003")) and
(OUT_MATERIALS."operation_date" like ("12.06.2003")) and
(IN_MATERIAL_ITEMS."operation_code" = IN_MATERIALS."operation_code") and
(OUT_MATERIAL_ITEMS."operation_code" = OUT_MATERIALS."operation_code")
group by MATERIALS."material_name"
Выдает пустой набор данных. Данные в таблицах присутствуют. Помогите исправить ошибку.
me2 (2003-06-14 11:24:00) [1]Я могу использовать хранимую процедуру, которая для каждого материала (входной параметр) будет выдавать его остаток на указанное число (тоже входной параметр). Потом мне надо на клиенте отображая список материалов видить остатки. Для DataSet можно создать вычисляемое поле и в OnCalcFields вызывать эту хранимую процедуру. Вопрос в том не будет ли это слишком большой нагрузгой на сервер и сеть?
me2 (2003-06-14 10:54:00) [2]Я поступил как советовал MsGuns © (13.06.03 16:20)
Использую запрос
select materials."material_name", materials."character_name",
materials."count_descr", materials."price", sum(operation_items."quantity")
from materials
left outer join operation_items on materials."material_code" = operation_items."material_code"
left outer join operations on operation_items."operation_code" = operations."operation_code" and
(operations."operation_date" = "11.06.2003")
group by materials."material_name", materials."character_name",
materials."count_descr", materials."price"
Запрос не учитывает дату, т.е. выводятся записи не зависимо от даты операции. Что не так?
me2 (2003-06-13 18:53:00) [3]Простите не увидел MsGuns © (13.06.03 18:45)
me2 (2003-06-13 18:52:00) [4]Посмотрите me2 (13.06.03 17:45)
MsGuns (2003-06-13 18:45:00) [5]>me2 (13.06.03 17:45)
Схем достаточно много. Все зависит от целей и средств ;))
Вообще-то есть 2 более-менее стандартные схемы:
1. Журнал
2. Счет-сальдо
При первой по Сущности "Счет-Субсчет" ведутся записи по дебету и кредиту, куда практически попадают все строки операций (фактур). При этом таблиц документов (2-й уровень) можно вообще не держать. Т.е. документы при необходимости "собираются" их журнала для просмотра или редактирования.
При второй документы как таковые присутствуют как таблицы, а в карточки "Счет-Субсчет" прописываются только данные из заголовков операций, т.е. суммарные обороты, которые модифицируют сальдо. Там же (в карточках) отражается и разноска проплат.
Склады выступают либо как отдельные сущности, либо как "партнеры" по общей схеме (в зависимости от внутр.особенностей движения ТМЦ, например есть ли перемещение между складами, есть ли розница и какая и т.д.)
Очень вкратце, возможно, не совсем точно, но я думаю, что, поразмыслив, можно "дорисовать" себе детали схемы.
Sandman25 (2003-06-13 17:46:00) [6]me2 (13.06.03 17:41)
Да. К тому же баланс по клиенту-поставщику получить легче - см. MsGuns © (13.06.03 17:39).
me2 (2003-06-13 17:45:00) [7]2 MsGuns © (13.06.03 17:39)
Как Вы посоветуете хранить данные о Поставщиках/Потребителях (с привязкой к операциям прихода и расхода)?
me2 (2003-06-13 17:41:00) [8]2 Sandman25 © (13.06.03 17:20)
> Все зависит от того, какие запросы потом будут использоваться
Т.е. проверяем поле типа операции и в зависиомти от результата имеем либо поставщика либо потребителя - так?
MsGuns (2003-06-13 17:39:00) [9]>me2 (13.06.03 17:14)
>У меня в таблицах заголовках IN_MATERIALS и OUT_MATERIALS было поле-ссылка на номер поставщика и на номер потребителя соответственно. Как правильно поступить при использовании одной таблицы - хранить оба номера, для каждой записи один из которых будет пуст?
Поставщик и Потребитель может быть одно и тоже лицо (фирма, организация). Поэтому если в БД иметь их как 2 РАЗНЫЕ сущности (и соотв-но 2 РАЗНЫХ спр-ка), то невозможно будет получить, к примеру, сводный баланс по партнеру.
Sandman25 (2003-06-13 17:37:00) [10]>Разве в IB такое есть?
Наверное, нет.
Напишите хранимую процедуру, вытаскивайте в цикле все материалы (по одному), рассчитывайте rashod, prihod и делайте suspend.
А из delphi вызывайте select * from proc_name(...)
PS. Я же предупреждал, что я на IB не работаю, поэтому могу дать только идею.
me2 (2003-06-13 17:27:00) [11]
> create temp table
Разве в IB такое есть?
Sandman25 (2003-06-13 17:20:00) [12]>Как правильно поступить при использовании одной таблицы - хранить оба номера, для каждой записи один из которых будет пуст?
Можно так, а можно и в одном поле. Все зависит от того, какие запросы потом будут использоваться.
Sandman25 (2003-06-13 17:15:00) [13]Я вообще бы использовал хранимую процедуру и временную таблицу.
create temp table tmp_materials
( mater_code char(10),
mater_name char(40),
prihod dec(18,2),
rashod dec(18,2)
) with no log;
insert into tmp_materials
(mater_code, mater_name)
select material_code, material_name
from materials;
update tmp_materials
set prihod = (select sum(p.quantity)
from in_material_items p
where p.material_code = tmp_materials.material_code;
update tmp_materials set prihod = 0 where prihod is null; // если надо
update tmp_materials
set rashod = (select sum(p.quantity)
from out_material_items p
where p.material_code = tmp_materials.material_code;
update tmp_materials set rashod = 0 where rashod is null; //
если надо
me2 (2003-06-13 17:14:00) [14]Да еще вопрос:
У меня в таблицах заголовках IN_MATERIALS и OUT_MATERIALS было поле-ссылка на номер поставщика и на номер потребителя соответственно. Как правильно поступить при использовании одной таблицы - хранить оба номера, для каждой записи один из которых будет пуст?
me2 (2003-06-13 17:08:00) [15]2 MsGuns © (13.06.03 16:55), Sandman25 © (13.06.03 17:02)
Так я использую join да и советов давали уже много, только
некоректно это все работает. Может Вы подскажите как правильно это сделать?
Sandman25 (2003-06-13 17:02:00) [16]me2
Все логично. Вы не можете суммировать в одном select и приход, и расход. Вот почему - например, у вас 1 приход (количество единиц 1) и 6 расходов (количество 5 в каждом). Тогда любой запрос найдет этот единственный приход, а затем будет перебирать все 6 расходов, заодно суммируя приход целых 6 раз (вместо 1).
В общем, нужно либо делать join, либо перепроектировать базу, храня все движение в одной таблице (приход с плюсом, расход с минусом).
MsGuns (2003-06-13 16:55:00) [17]>me2 (13.06.03 16:47)
Можно. Используя Outer|Inner JOIN или аккумулятор UNION
me2 (2003-06-13 16:47:00) [18]2 MsGuns © (13.06.03 16:20)
Отличый совет. Спасибо. Сейчас займусь переделкой. Но мне все-таки интересно - можно ли добиться того чего я хочу на существующей структуре БД?
MsGuns (2003-06-13 16:20:00) [19]Самый лучший способ в этом случае (ИМХО) - использование JOUN с выводом в рез.набор пары наборов полей (кол-во, цена, сумма) для вх и вых док-тов (операций). А вообще-то я бы не рекомендовал заводить для каждоготипа операции (вида документа: прихода, отгрузки, перемещения, списания и т.д.) отдельную таблицу. Все прекрасно держится в одной паре таблиц:
1. Заголовки (дата, №, тип док-та, суммы и т.д.)
2. Фактура (код, кол-во, сумма и т.д.), причем сумма и кол-во
положительные для приходных или или отрицательных для расходных документов.
me2 (2003-06-13 16:07:00) [20]Данный запрос отлично работает только до тех пор, пока в таблицах прихода и расхода (IN_MATERIAL_ITEMS, OUT_MATERIAL_ITEMS) по одной записи. Например, у меня пришло 3434 + 100, ушло 12, а запрос выдает, что осталось 3510, т.е получается, что берется два раза из таблицы расхода по 12.