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

Модераторы: kdv, CyberMax

Ответить
connor74
Сообщения: 11
Зарегистрирован: 18 июн 2007, 08:24

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

Сообщение connor74 » 28 июн 2007, 23:30

Здравствуйте уважаемые форумчане.

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

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

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

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 29 июн 2007, 10:05

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

connor74
Сообщения: 11
Зарегистрирован: 18 июн 2007, 08:24

Сообщение connor74 » 30 июн 2007, 17:29

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
Заранее благодарен за помощь
Последний раз редактировалось connor74 01 июл 2007, 10:06, всего редактировалось 1 раз.

Attid
Спец
Сообщения: 377
Зарегистрирован: 14 ноя 2006, 09:58

Сообщение Attid » 01 июл 2007, 09:22

ну ты бы в тег [ 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

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 02 июл 2007, 09:54

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, в принципе. Как это запихнуть в один запрос пока не представляю.
Если делать на клиенте, я бы сделал два датасэта и прокручивал бы их за один проход параллельно, вот БЫ сделать такой финт в ХП. Хотя мож я просто от жизни поотстал и уже можно... :)

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 02 июл 2007, 11:23

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

connor74
Сообщения: 11
Зарегистрирован: 18 июн 2007, 08:24

Сообщение connor74 » 02 июл 2007, 11:24

Спасибо всем огромное за помощь, задачу победил но пришлось действовать весьма нерацональным способом:

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

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

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

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 02 июл 2007, 15:13

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

Attid
Спец
Сообщения: 377
Зарегистрирован: 14 ноя 2006, 09:58

Сообщение Attid » 02 июл 2007, 20:40

connor74 писал(а): Кстати все таки интерес к реализации без дополнительной таблицы остался
тебе предложили 2 варианта. не один не работает ?

Ответить