Страница 1 из 1

Нужна помощь в написании ХП или запрос (ФИФО)

Добавлено: 28 июн 2007, 23:30
connor74
Здравствуйте уважаемые форумчане.

Что то никак не приходит в голову как оформить следующую процедуру.
Есть таблица покупок и продаж (операции) товаров в которой следующие поля:

ID BIGINT
TYPEOPER SMALLINT (тип операции 1-покупка, 2-продажа)
ITEM INTEGER (номер товара)
VOLUME INTEGER

Необходимо чтобы запрос выводил данные таким обарзом чтобы каждая строка отражала движение товара, т.е. предположим куплено в одной операции 100 ед товара 1, а продавалось 2-мя операциями по 80 и 20, соответственно 2 строки в результирующей таблице. Или наоборот куплено 2-мя операциями 30 и 70 а продано одной 100 ед (опять 2 строки). Ну и самый простой вариант когда куплено 100 и продано 100, тогда одна строк (по методу ФИФО).:

ITEM VOLUME_BUY VOLUME_SELL

Вот что то и не могу придумать как побороть такую задачу.
Благодярен за любую помощь

Добавлено: 29 июн 2007, 10:05
Ivan_Pisarevsky
Набросай с десяток строк в исходной таблице и результат в виде ТАБЛИЦЫ, типа так есть: ... так хочу видеть: ...

Добавлено: 30 июн 2007, 17:29
connor74
Ivan_Pisarevsky писал(а):Набросай с десяток строк в исходной таблице и результат в виде ТАБЛИЦЫ, типа так есть: ... так хочу видеть: ...
Значит исходная таблица OPERATION:
ID - индекс
TYPEOPER - тип операции (1-покупка, 2-продажа)
ITEM - номер товара
VOLUME - количество
PRICE - цена (покупки/продажи)

Код: Выделить всё

ID | TYPEOPER | ITEM | VOLUME | PRICE
1 | 1 | 1 | 50 | 20.50
2 | 1 | 1 | 80 | 21.00
3 | 2 | 1 | 100 | 25.20
4 | 1 | 2 | 500 | 12.30
5 | 2 | 2 | 500 | 18.45
6 | 1 | 1 | 30 | 21.20
7 | 2 | 1 | 60 | 25.20
8 | 1 | 3 | 4 | 103.42
9 | 2 | 3 | 2 | 140.00
10 | 2 | 3 | 1 | 141.00
Результат запроса (то что нужно вывести):

Код: Выделить всё

ID_BUY | ID_SELL | ITEM | VOLUME | PRICE_BUY | PRICE_SELL
1 | 3 | 1 | 50 | 20.50 | 25.20
2 | 3 | 1 | 50 | 21.00 | 25.20
4 | 5 | 2 | 500 | 12.30 | 18.45
2 | 7 | 1 | 30  | 21.00 | 25.20
6 | 7 | 1 | 30 | 21.20 | 25.20
8 | 9 | 3 | 2 | 103.42 | 140.00
8 | 10 | 3 | 1 | 103.42 | 141
Заранее благодарен за помощь

Добавлено: 01 июл 2007, 09:22
Attid
ну ты бы в тег [ code] выделил, а то ну совсем не понятно.
вот про третью строчку не понятно, она не парная, потому что её не продали ? а у нее кол-во одинаковое.

ну что ХП это уже понятно =) хотя и блоком можно .

может ошибаюсь но должно быть что-то вроде:

Код: Выделить всё

--переменых паручку
countrecord1 integer;
countrecord2 integer;
--выбираем все что купили 
for select *,count(1) from OPERATION
join **
group by *
where TYPEOPER = 1
into ***,countrecord1 --содержит за сколько операций купили
do begin
  suspend;
  --
  select *,count(1) from OPERATION
  join **
  where TYPEOPER = 2
  and  ITEM = :ITEM 
  group by *
  into ***, countrecord2 --содержит за сколько операций продали
  do if (countrecord1 <> countrecord2) then
       suspend; -- отправляем только если кол-во разное ставишь условие нужное тебе
  
end

Добавлено: 02 июл 2007, 09:54
Ivan_Pisarevsky
to Attid
Често говоря твой пост не понял, как можно строить фифо без ордер бая по дате операции как-то в голове не очень укладывается...

ИМХО примерно следущее:

переменные
curr_date_oper /*текущая дата продажи*/
curr_oper /*текущая продажа, ключ*/
not_sale /*остаток товара*/

for
select ...
from operation
where <все операции прихода по выбранным товарам за требуемый период>
order by item, date_oper
into <переменные>
do
begin
while not_sale >0
do
begin
/*берем первый расход по данному товару*/
select first 1 ...
from operation
where <расход по выбранному товару за требуемый период при этом берем больше текущей даты и больше текущей опреции расхода, чтоб не зациклится>
order by date_oper, id_oper
into <переменные>;
/*закрываем приход расходом, пока есть ненулевой остаток, как только попытка превысить прокручиваемся на следущую запись в приходе и пошли по новой, попутно продвигаем текущую дату продажи и текущий остаток*/
suspend;
end
end

Алгоритм где-то так, можно вместо while+first сделать for select, в принципе. Как это запихнуть в один запрос пока не представляю.
Если делать на клиенте, я бы сделал два датасэта и прокручивал бы их за один проход параллельно, вот БЫ сделать такой финт в ХП. Хотя мож я просто от жизни поотстал и уже можно... :)

Добавлено: 02 июл 2007, 11:23
WildSery
Ivan_Pisarevsky писал(а):Если делать на клиенте, я бы сделал два датасэта и прокручивал бы их за один проход параллельно, вот БЫ сделать такой финт в ХП. Хотя мож я просто от жизни поотстал и уже можно... :)
Сразу скажу - пост и алгоритм не читал.
Если проход без возврата на предыдущие записи - то курсоры в 2-ке и старше - самое то :wink:

Добавлено: 02 июл 2007, 11:24
connor74
Спасибо всем огромное за помощь, задачу победил но пришлось действовать весьма нерацональным способом:

Создал новую таблицу RESULTS, куда сводятся сделки по продаже и соответсвующие им по покупке (внешний ключ), с явным указанием количества. Также в табличку оператион добавил поле SELL_VOLUME, куда вносится объем продажи и соответственно если объем продажи равняется объему покупки то больше эта строка не участвует.

Вобщем все работает но понимаю что далеко не идеальный вариант.

Кстати все таки интерес к реализации без дополнительной таблицы остался

Добавлено: 02 июл 2007, 15:13
Ivan_Pisarevsky
WildSery писал(а):Если проход без возврата на предыдущие записи - то курсоры в 2-ке и старше - самое то :wink:
Собстно да. Блин, текучка никак не позволяет пошшупать двойку за интимные места, вот как чуял что курсоры именно про то, когда по диагонали релизноты читал. Ну да ладно спасибо за наметку. :)

Добавлено: 02 июл 2007, 20:40
Attid
connor74 писал(а): Кстати все таки интерес к реализации без дополнительной таблицы остался
тебе предложили 2 варианта. не один не работает ?